home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / edit / wpformat.src < prev   
Encoding:
Text File  |  1988-05-03  |  475.4 KB  |  10,499 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --prntglob
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4.  
  5.   --$$$+ PRNTGLOB
  6.  
  7.   --
  8.   -- File 0xx
  9.   --
  10.   -- Formatter Written By Robert S. Cymbalski
  11.   --                      Science Applications International Corporation
  12.   --                      Energy Systems Group
  13.   --                      Ada Software Development Project Team
  14.   --                      2280 U.S. Highway 19 North, Suite 120
  15.   --                      Clearwater, Florida  33575
  16.   --
  17.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  18.   --
  19.       
  20.   with text_io            ; -- for input 
  21.   with direct_io          ; -- for output 
  22.   with io_exceptions      ;
  23.   with unchecked_conversion ;
  24.    
  25.   with string_library  ;
  26.   use  string_library  ;
  27.    
  28.   with basic_io_system ;
  29.    
  30.   with crt_windows     ;
  31.   use  crt_windows     ;
  32.    
  33.   with Wordp_Globals   ;
  34.   use  Wordp_Globals   ;
  35.  
  36.   Package Printer_globals is
  37.     
  38.     ---------------------------------------------------------------------------
  39.     --                                                                       --
  40.     --  Start of types which are used by global callers to text formatter    --
  41.     --                                                                       --
  42.     ---------------------------------------------------------------------------
  43.      
  44.     type printer_type is ( z_pdumb , z_pbackspace , z_qume , z_citoh , 
  45.                            z_diablo ,
  46.                            z_HP_laser_Printer ,
  47.                            z_xerox , z_n3500 , z_n3510 , z_n3550 ,
  48.                            z_n3515 , z_cent737 , z_aj832 , z_starwriter ,
  49.                            z_dataproducts , z_la50 , z_lqp02 , z_la100draft ,
  50.                            z_la100medium , z_la100high ,
  51.                            z_unknown ) ;
  52.       
  53.     type printer_accessories_type
  54.                               is ( none , trayloader , dual_tray , mech_tray ) ;
  55.         
  56.     subtype Font_Number is integer ;
  57.      
  58.     -- Now, format commands
  59.      
  60.     type ot_format_type  is (ot_fancy , ot_plain) ;
  61.     type where_to_type   is (to_screen , to_printer , to_file) ;
  62.     type inp_source_type is (fm_database , fm_text) ;
  63.       
  64.     type formatter_environment is 
  65.            record
  66.              Printer_Brand      : Printer_Type             := z_unknown ;
  67.              Printer_Accessories: Printer_Accessories_Type := none      ;
  68.              Continuous_Forms   : Boolean                  := true      ;
  69.              number_of_copies_to_print  : integer          := 1         ;
  70.              First_Page_to_Print        : integer          := 1         ;
  71.              Last_Page_to_Print         : integer          := integer'last ;
  72.              ot_format          : ot_format_type  := ot_fancy    ;
  73.              where_to           : where_to_type   := to_printer  ;
  74.              inp_source         : inp_source_type := fm_text     ;
  75.              Database_File_Name : ascii_text_file_name     := no_file   ;
  76.              Font_To_Use        : Font_Number              := 0         ;
  77.              Show_Output_Status : Boolean                  := true      ;
  78.            end record ;
  79.      
  80.     default_environment : constant formatter_environment :=
  81.                                 ( z_unknown , none , true , 1 , 1 , 
  82.                                   integer'last , ot_fancy , to_printer , 
  83.                                   fm_text , no_file , 0 , true  ) ;
  84.      
  85.     ---------------------------------------------------------------------------
  86.     --                                                                       --
  87.     --  End of types which are used by global callers to text formatter      --
  88.     --                                                                       --
  89.     ---------------------------------------------------------------------------
  90.      
  91.     -- Font Information
  92.      
  93.     Font_file  : constant string := "TYPEFONT.DATA" ;
  94.      
  95.     subtype Font_name_type is string ( 1 .. 25 ) ;
  96.     subtype extended_character is basic_io_system.extended_character ;
  97.     type    a_map_string is array ( 1 .. 3 ) of extended_character ;
  98.     subtype horizontal_measurement is integer 
  99.                                    range - 14 * 720 .. 14 * 720 ;
  100.                               -- because largest measurement is 14" paper wide 
  101.                               -- by 720 points per inch
  102.     subtype vertical_measurement is integer range 0 .. 14 * 720 ;
  103.                               -- becuase largest vertical measurement is 14" 
  104.                               -- long by 720 per inch
  105.     type    width_array is array ( extended_character ) 
  106.                             of horizontal_measurement ;
  107.     type    hammer_array is array ( extended_character ) of integer ;
  108.     type    map_array is array ( extended_character ) of a_map_string ;
  109.     type    Font_type is 
  110.               record 
  111.                 name : Font_name_type ;
  112.                 Number : Font_Number  ;
  113.                 vertical_points_per_inch   : vertical_measurement   ;
  114.                 horizontal_points_per_inch : horizontal_measurement ;
  115.                 Font_Width : horizontal_measurement ;
  116.                 Font_Height: Vertical_Measurement   ;
  117.                 width : width_array ;
  118.                 hammer_intensity : hammer_array ;
  119.                 Mappings_Necessary : boolean ;
  120.                 map_string : map_array ;
  121.               end record ;
  122.      
  123.     default_font        : font_type                 ;
  124.                           -- assigned in the initialization code 
  125.      
  126.     Permanent_Font      : font_type                 ;
  127.     Temporary_Font      : font_type                 ;
  128.     Current_Font        : font_type                 ;
  129.     Font_Width          : horizontal_measurement    ; -- For Permanent Font
  130.     Space_Width         : horizontal_measurement    ; -- For Current Font
  131.     Half_Space_Width    : horizontal_measurement    ; -- For Current Font
  132.      
  133.     default_printer : constant ascii_text_file_name := "PRINTER:            ";
  134.     default_console : constant ascii_text_file_name := "CONSOLE:            ";
  135.      
  136.     initial_environment : formatter_environment ;
  137.     current_environment : formatter_environment ;
  138.      
  139.     type smart_printer_type is (z_dumb , z_backspace , z_smart) ;
  140.       
  141.     type proportional_printer_type is (z_p_centronics , z_p_qume , z_p_diablo) ;
  142.       
  143.     z_proportional  : proportional_printer_type ;
  144.     z_smart_printer : smart_printer_type ;
  145.     z_printer       : printer_type ;
  146.     z_forward       : boolean ;
  147.      
  148.     permanent_printer : printer_type ;
  149.     printer_accessories: printer_accessories_type ;
  150.     printer_points_per_inch : horizontal_measurement ;
  151.     printer_vertical_per_inch : vertical_measurement ;
  152.     we_have_some_tray_loader   : boolean ;
  153.     we_have_single_tray_loader : boolean ;
  154.     we_have_dual_tray_loader   : boolean ;
  155.      
  156.     master_window : crt_windows.window_pointer ;
  157.      
  158.     type input_file_type is ( main_input_file , alternate_input_file , 
  159.                               variable_input_file ) ;
  160.                           
  161.     main_in_file_name : ascii_text_file_name := no_file ;
  162.     alt_in_file_name  : ascii_text_file_name := no_file ;
  163.     var_in_file_name  : ascii_text_file_name := no_file ;
  164.     ot_file_name      : ascii_text_file_name := no_file ;
  165.      
  166.     copies_printed_so_far: integer ;
  167.     Physical_Page_Number : Integer ;
  168.     Physical_Input_Lines : Integer ;
  169.     Physical_Output_Lines: Integer ;
  170.      
  171.     where_to_read   : input_file_type   ;
  172.      
  173.     extended_nul       : constant extended_character 
  174.                          := extended_character ( character'pos( ascii.nul ) ) ; 
  175.     -- extended_soh       : constant extended_character 
  176.                       -- := extended_character ( character'pos( ascii.soh ) ) ; 
  177.     -- extended_stx       : constant extended_character 
  178.                       -- := extended_character ( character'pos( ascii.stx ) ) ; 
  179.     -- extended_etx       : constant extended_character 
  180.                       -- := extended_character ( character'pos( ascii.etx ) ) ; 
  181.     -- extended_eot       : constant extended_character 
  182.                       -- := extended_character ( character'pos( ascii.eot ) ) ; 
  183.     -- extended_enq       : constant extended_character 
  184.                       -- := extended_character ( character'pos( ascii.enq ) ) ; 
  185.     -- extended_ack       : constant extended_character 
  186.                       -- := extended_character ( character'pos( ascii.ack ) ) ; 
  187.     -- extended_bel       : constant extended_character 
  188.                       -- := extended_character ( character'pos( ascii.bel ) ) ; 
  189.     extended_bs        : constant extended_character 
  190.                          := extended_character ( character'pos( ascii.bs  ) ) ; 
  191.     extended_ht        : constant extended_character 
  192.                          := extended_character ( character'pos( ascii.ht  ) ) ; 
  193.     extended_lf        : constant extended_character 
  194.                          := extended_character ( character'pos( ascii.lf  ) ) ; 
  195.     -- extended_vt        : constant extended_character 
  196.                       -- := extended_character ( character'pos( ascii.vt  ) ) ; 
  197.     extended_ff        : constant extended_character 
  198.                          := extended_character ( character'pos( ascii.ff  ) ) ; 
  199.     extended_cr        : constant extended_character 
  200.                          := extended_character ( character'pos( ascii.cr  ) ) ; 
  201.     extended_so        : constant extended_character 
  202.                          := extended_character ( character'pos( ascii.so  ) ) ; 
  203.     extended_si        : constant extended_character 
  204.                          := extended_character ( character'pos( ascii.si  ) ) ; 
  205.     -- extended_dle       : constant extended_character 
  206.                       -- := extended_character ( character'pos( ascii.dle ) ) ; 
  207.     -- extended_dc1       : constant extended_character 
  208.                       -- := extended_character ( character'pos( ascii.dc1 ) ) ; 
  209.     -- extended_dc2       : constant extended_character 
  210.                       -- := extended_character ( character'pos( ascii.dc2 ) ) ; 
  211.     -- extended_dc3       : constant extended_character 
  212.                       -- := extended_character ( character'pos( ascii.dc3 ) ) ; 
  213.     -- extended_dc4       : constant extended_character 
  214.                       -- := extended_character ( character'pos( ascii.dc4 ) ) ; 
  215.     -- extended_nak       : constant extended_character 
  216.                       -- := extended_character ( character'pos( ascii.nak ) ) ; 
  217.     -- extended_syn       : constant extended_character 
  218.                       -- := extended_character ( character'pos( ascii.syn ) ) ; 
  219.     -- extended_etb       : constant extended_character 
  220.                       -- := extended_character ( character'pos( ascii.etb ) ) ; 
  221.     -- extended_can       : constant extended_character 
  222.                       -- := extended_character ( character'pos( ascii.can ) ) ; 
  223.     -- extended_em        : constant extended_character 
  224.                       -- := extended_character ( character'pos( ascii.em  ) ) ; 
  225.     -- extended_sub       : constant extended_character 
  226.                       -- := extended_character ( character'pos( ascii.sub ) ) ; 
  227.     extended_esc       : constant extended_character 
  228.                          := extended_character ( character'pos( ascii.esc ) ) ;
  229.     -- extended_fs        : constant extended_character 
  230.                       -- := extended_character ( character'pos( ascii.fs  ) ) ; 
  231.     -- extended_gs        : constant extended_character 
  232.                       -- := extended_character ( character'pos( ascii.gs  ) ) ; 
  233.     -- extended_rs        : constant extended_character 
  234.                       -- := extended_character ( character'pos( ascii.rs  ) ) ; 
  235.     -- extended_us        : constant extended_character 
  236.                       -- := extended_character ( character'pos( ascii.us  ) ) ; 
  237.     extended_space     : constant extended_character
  238.                          := extended_character ( character'pos( ' '       ) ) ; 
  239.     extended_zero      : constant extended_character
  240.                          := extended_character ( character'pos( '0'       ) ) ;
  241.     extended_one       : constant extended_character
  242.                          := extended_character ( character'pos( '1'       ) ) ;
  243.     -- extended_two       : constant extended_character
  244.                       -- := extended_character ( character'pos( '2'       ) ) ;
  245.     -- extended_three     : constant extended_character
  246.                       -- := extended_character ( character'pos( '3'       ) ) ;
  247.     -- extended_four      : constant extended_character
  248.                       -- := extended_character ( character'pos( '4'       ) ) ;
  249.     -- extended_five      : constant extended_character
  250.                       -- := extended_character ( character'pos( '5'       ) ) ;
  251.     -- extended_six       : constant extended_character
  252.                       -- := extended_character ( character'pos( '6'       ) ) ;
  253.     -- extended_seven     : constant extended_character
  254.                       -- := extended_character ( character'pos( '7'       ) ) ;
  255.     -- extended_eight     : constant extended_character
  256.                       -- := extended_character ( character'pos( '8'       ) ) ;
  257.     extended_nine      : constant extended_character
  258.                          := extended_character ( character'pos( '9'       ) ) ;
  259.     extended_UC_A      : constant extended_character
  260.                          := extended_character ( character'pos( 'A'       ) ) ;
  261.     extended_UC_S      : constant extended_character
  262.                          := extended_character ( character'pos( 'S'       ) ) ;
  263.     extended_UC_Z      : constant extended_character
  264.                          := extended_character ( character'pos( 'Z'       ) ) ;
  265.     extended_lc_a      : constant extended_character
  266.                          := extended_character ( character'pos( 'a'       ) ) ;
  267.     extended_lc_z      : constant extended_character
  268.                          := extended_character ( character'pos( 'z'       ) ) ;
  269.     extended_quote     : constant extended_character
  270.                          := extended_character ( character'pos( '''       ) ) ;
  271.     extended_exclam    : constant extended_character 
  272.                          := extended_character ( character'pos( ascii.exclam)); 
  273.     extended_quotation : constant extended_character 
  274.                          := extended_character(character'pos(ascii.quotation)); 
  275.     -- extended_sharp     : constant extended_character 
  276.                       -- := extended_character ( character'pos( ascii.sharp )); 
  277.     -- extended_dollar    : constant extended_character 
  278.                       -- := extended_character ( character'pos( ascii.dollar)); 
  279.     extended_percent   : constant extended_character 
  280.                          := extended_character ( character'pos(ascii.percent)); 
  281.     extended_ampersand : constant extended_character 
  282.                          := extended_character(character'pos(ascii.ampersand)); 
  283.     -- extended_colon     : constant extended_character 
  284.                       -- := extended_character ( character'pos( ascii.colon )); 
  285.     -- extended_semicolon : constant extended_character 
  286.                       -- := extended_character(character'pos(ascii.semicolon)); 
  287.     -- extended_query     : constant extended_character 
  288.                       -- := extended_character ( character'pos( ascii.query )); 
  289.     extended_at_sign   : constant extended_character 
  290.                          := extended_character ( character'pos(ascii.at_sign)); 
  291.     -- extended_l_bracket : constant extended_character 
  292.                       -- := extended_character(character'pos(ascii.l_bracket)); 
  293.     -- extended_back_slash: constant extended_character 
  294.                       -- :=extended_character(character'pos(ascii.back_slash)); 
  295.     -- extended_r_bracket : constant extended_character 
  296.                       -- := extended_character(character'pos(ascii.r_bracket)); 
  297.     -- extended_circumflex: constant extended_character 
  298.                       -- :=extended_character(character'pos(ascii.circumflex)); 
  299.     extended_underline : constant extended_character
  300.                          := extended_character(character'pos(ascii.underline));
  301.     -- extended_grave     : constant extended_character 
  302.                       -- := extended_character ( character'pos( ascii.grave )); 
  303.     -- extended_l_brace   : constant extended_character 
  304.                       -- := extended_character ( character'pos(ascii.l_brace)); 
  305.     -- extended_bar       : constant extended_character 
  306.                       -- := extended_character ( character'pos( ascii.bar ) ) ; 
  307.     -- extended_r_brace   : constant extended_character 
  308.                       -- := extended_character ( character'pos(ascii.r_brace)); 
  309.     -- extended_tilde     : constant extended_character 
  310.                       -- := extended_character ( character'pos( ascii.tilde )); 
  311.     -- extended_plus      : constant extended_character
  312.                       -- := extended_character ( character'pos( '+'       ) ) ;
  313.     extended_minus     : constant extended_character
  314.                          := extended_character ( character'pos( '-'       ) ) ;
  315.     extended_del       : constant extended_character 
  316.                          := extended_character ( character'pos( ascii.del ) ) ; 
  317.  
  318.     procedure open_for_read ( file_to_open    : input_file_type ;
  319.                               file_name       : in out ascii_text_file_name ;
  320.                               successfull     : out boolean            ) ;
  321.      
  322.     procedure select_for_read( file_to_select : input_file_type ) ;
  323.      
  324.     procedure read_next_line ( new_line    : out pstring ;
  325.                                end_of_file : out boolean ) ;
  326.      
  327.     procedure create_output_file   ( new_file_name: in ascii_text_file_name ;
  328.                                      successfull  :    out boolean          ) ;
  329.      
  330.     procedure close_output_file ( successfull : out boolean ) ;
  331.      
  332.     Procedure file_out(char1 : in character ; 
  333.                        char2 : in character := ascii.nul ;
  334.                        char3 : in character := ascii.nul ) ;
  335.       -- note that the only way to send a nul out is to send it as
  336.       -- the first parameter
  337.       
  338.     Procedure file_out(char1 : in extended_character ) ;
  339.       -- note that the only way to send a nul out is to send it as
  340.       -- the first parameter
  341.       
  342.     Procedure file_out(char1 : in extended_character ; 
  343.                        char2 : in extended_character ) ;
  344.       -- note that the only way to send a nul out is to send it as
  345.       -- the first parameter
  346.       
  347.     Procedure file_out(char1 : in extended_character ; 
  348.                        char2 : in extended_character ;
  349.                        char3 : in extended_character ) ;
  350.       -- note that the only way to send a nul out is to send it as
  351.       -- the first parameter
  352.       
  353.     Procedure z_file_out(char1 : in character ; 
  354.                          char2 : in character := ascii.nul ;
  355.                          char3 : in character := ascii.nul ) ;
  356.       -- note that the only way to send a nul out is to send it as
  357.       -- the first parameter
  358.       
  359.     procedure end_dumb_output_line ;
  360.       -- end an output line to a "dumb" device
  361.        
  362.     Procedure otsxy( x , y : in integer ; s : in string) ;
  363.       
  364.     Procedure otnxy( x , y , n : in integer ; len : in integer := 1 ) ;
  365.       
  366.     Function Stall ( done_on_q : in boolean ) return boolean ; 
  367.      
  368.     Procedure change_printer( new_printer : in printer_type ) ;
  369.       
  370.     Function Odd ( I : Integer ) return boolean ;
  371.    
  372.     Procedure UpDate_Status ;
  373.    
  374.     procedure initialize_Printer_Globals_for_a_new_document ;
  375.    
  376.     procedure finish_Printer_Globals_for_an_old_document    ;
  377.      
  378.     procedure close_Printer_Globals ;
  379.      
  380.   end ;
  381.     
  382.   Package body Printer_globals is
  383.       
  384.     package formatter_io renames text_io ; -- is new direct_io ( character ) ;
  385.    
  386.     -- the following is there because of a(nother!) telesoft bug... -----------
  387.     function bobs_convert is new unchecked_conversion( integer , character ) ;
  388.     bobs_cr     : constant character := ascii.cr ; -- bobs_convert ( 141 ) ;
  389.     bobs_lf     : constant character := ascii.lf ; -- bobs_convert ( 138 ) ;
  390.     Telesoft_Text_Io_Bugs        : constant boolean := true  ;
  391.     no_movement_on_printer_line_yet       : boolean := true  ;
  392.     A_Line_Feed_Skipped_Already           : boolean := true  ;
  393.     -- end of special stuff for telesoft bug                        -----------
  394.      
  395.     ot_file : formatter_io.file_type ;
  396.      
  397.     main_in_file    : text_io.file_type ;
  398.     alt_in_file     : text_io.file_type ;
  399.     var_in_file     : text_io.file_type ;
  400.     -- crt_ot_file     : text_io.file_type ;
  401.      
  402.     procedure open_for_read ( file_to_open    : input_file_type ;
  403.                               file_name       : in out ascii_text_file_name ;
  404.                               successfull     : out boolean            ) is
  405.       -- look for the orig_file_name on the appropriate disks.  Return
  406.       -- successfull if found, and also set the final_file_name as 
  407.       -- the fully elaborated file path/name.  Open the file setting
  408.       -- the handle 
  409.     begin -- open_for_read 
  410.       case file_to_open is
  411.         when main_input_file => open_for_read( main_in_file , file_name , 
  412.                                                successfull ) ;
  413.                                 main_in_file_name := file_name ;
  414.         when alternate_input_file  => open_for_read( alt_in_file  , file_name , 
  415.                                                      successfull ) ;
  416.                                       alt_in_file_name  := file_name ;
  417.         when variable_input_file  => open_for_read( var_in_file  , file_name ,
  418.                                                     successfull ) ;
  419.                                      var_in_file_name  := file_name ;
  420.       end case ;
  421.     end open_for_read ;
  422.      
  423.     procedure select_for_read( file_to_select : input_file_type ) is
  424.     begin -- select_for_read
  425.       where_to_read := file_to_select ;
  426.     end select_for_read ;
  427.      
  428.     procedure read_next_line ( new_line    : out pstring ;
  429.                                end_of_file : out boolean ) is
  430.       in_line : string ( 1 .. 255 ) ;
  431.       in_leng : integer ;
  432.     begin -- read_next_line
  433.       case where_to_read is
  434.         when main_input_file       => if text_io.end_of_file( main_in_file) then
  435.                                         end_of_file := true ;
  436.                                         new_line := blank_line ;
  437.                                       else
  438.                                         -- we are ready to read...
  439.                                         -- Note that for speed, we are reading
  440.                                         -- directly into the PString array...
  441.                                         text_io.get_line( main_in_file ,
  442.                                                         new_line.data ,
  443.                                                         new_line.actual_length);
  444.                                         end_of_file := false ;
  445.                                       end if ;
  446.         when alternate_input_file  => if text_io.end_of_file( alt_in_file ) then
  447.                                         end_of_file := true ;
  448.                                         new_line := blank_line ;
  449.                                       else
  450.                                         -- we are ready to read...
  451.                                         -- Note that for speed, we are reading
  452.                                         -- directly into the PString array...
  453.                                         text_io.get_line( alt_in_file ,
  454.                                                         new_line.data ,
  455.                                                         new_line.actual_length);
  456.                                         end_of_file := false ;
  457.                                       end if ;
  458.         when variable_input_file   => if text_io.end_of_file( var_in_file ) then
  459.                                         end_of_file := true ;
  460.                                         new_line := blank_line ;
  461.                                       else
  462.                                         -- we are ready to read...
  463.                                         -- Note that for speed, we are reading
  464.                                         -- directly into the PString array...
  465.                                         text_io.get_line( var_in_file ,
  466.                                                         new_line.data ,
  467.                                                         new_line.actual_length);
  468.                                         end_of_file := false ;
  469.                                       end if ;
  470.       end case ;
  471.     end read_next_line ;
  472.      
  473.     procedure create_output_file   ( new_file_name: in ascii_text_file_name ;
  474.                                      successfull  :    out boolean          ) is
  475.       -- open the file for output and return status
  476.     begin -- create
  477.       if formatter_io.is_open(ot_file) then
  478.         formatter_io.close(ot_file);
  479.       end if ;
  480.       -- Now, we need to see if it is an open or create.....
  481.       if new_file_name = default_printer 
  482.       or else new_file_name = default_console then
  483.         -- open it...
  484.         formatter_io.open  ( ot_file , formatter_io.out_file ,
  485.                              no_blanks(new_file_name));
  486.       else
  487.         -- create it...
  488.         formatter_io.create( ot_file , formatter_io.out_file ,
  489.                              no_blanks(new_file_name));
  490.       end if ;
  491.       ot_file_name := new_file_name ;
  492.       successfull := true ; 
  493.     exception 
  494.       -- when io_exceptions.status_error => put("StatusError");
  495.       -- when io_exceptions.name_error   => put("NameError  ");
  496.       -- when io_exceptions.use_error    => put("UseError   ");
  497.       when others                    => successfull := false ;
  498.     end create_output_file ;
  499.      
  500.     procedure close_output_file ( successfull : out boolean ) is
  501.     begin -- close_output_file
  502.       -- for posn in 1 .. 256 loop
  503.         -- file_out(character'val(26)) ;
  504.       -- end loop ;
  505.       formatter_io.close ( ot_file ) ;
  506.       successfull := true ; 
  507.     exception 
  508.       when others                    => successfull := false ;
  509.     end close_output_file ;
  510.      
  511.     Procedure file_out(char1 : in character ; 
  512.                        char2 : in character := ascii.nul ;
  513.                        char3 : in character := ascii.nul ) is
  514.       -- the following code required by wicat...
  515.       c1 , c2 , c3 : character ;
  516.     begin -- file_out
  517.       -- we also know where_to = to_file or something...
  518.       c1 := char1 ;
  519.       -- formatter_io.write( ot_file , c1 ) ;
  520.       -- if char2 /= ascii.nul then
  521.         -- c2 := char2 ;
  522.         -- formatter_io.write( ot_file , c2 ) ;
  523.         -- if char3 /= ascii.nul then
  524.           -- c3 := char3 ;
  525.           -- formatter_io.write( ot_file , c3 ) ;
  526.         -- end if ;
  527.       -- end if ;
  528.       --
  529.       If Telesoft_Text_Io_Bugs  
  530.       and then char2 = ascii.nul then
  531.         if c1 = ascii.cr then
  532.           c1 := bobs_cr ;
  533.         elsif c1 = ascii.lf then
  534.           c1 := bobs_lf ;
  535.         end if ;
  536.         -- we are possibly processing a <cr> or <lf>
  537.         -- only a single character to be worked....check out for 
  538.         -- trying to fix telesoft Text I/O problems
  539.         if no_movement_on_printer_line_yet then -- for telesoft problems
  540.           if c1 = bobs_cr then
  541.             return ; -- don't do anything
  542.           elsif c1 = bobs_lf then
  543.             if not A_Line_Feed_Skipped_Already then
  544.               a_line_feed_skipped_already := true ;
  545.               return ;
  546.             end if ;
  547.           else
  548.             no_movement_on_printer_line_yet := false ;
  549.           end if ;
  550.         elsif c1 = bobs_cr then
  551.           no_movement_on_printer_line_yet := true ;
  552.           a_line_feed_skipped_already     := false ;
  553.         end if ; -- for telesoft problems
  554.       else
  555.         no_movement_on_printer_line_yet := false ; -- for telesoft problems
  556.       end if ;
  557.       --
  558.       formatter_io.put( ot_file , c1 ) ;
  559.       if char2 /= ascii.nul then
  560.         c2 := char2 ;
  561.         formatter_io.put( ot_file , c2 ) ;
  562.         if char3 /= ascii.nul then
  563.           c3 := char3 ;
  564.           formatter_io.put( ot_file , c3 ) ;
  565.         end if ;
  566.       end if ;
  567.     end file_out ;
  568.       
  569.     Procedure file_out(char1 : in extended_character ) is
  570.       -- note that the only way to send a nul out is to send it as
  571.       -- the first parameter
  572.     begin -- file_out
  573.       file_out ( character'val( char1 ) ) ;
  574.     end file_out ;
  575.      
  576.     Procedure file_out(char1 : in extended_character ; 
  577.                        char2 : in extended_character ) is
  578.       -- note that the only way to send a nul out is to send it as
  579.       -- the first parameter
  580.     begin -- file_out
  581.       file_out ( character'val( char1 ) ,
  582.                  character'val( char2 ) ) ;
  583.     end file_out ;
  584.      
  585.     Procedure file_out(char1 : in extended_character ; 
  586.                        char2 : in extended_character ;
  587.                        char3 : in extended_character ) is
  588.       -- note that the only way to send a nul out is to send it as
  589.       -- the first parameter
  590.     begin -- file_out
  591.       file_out ( character'val( char1 ) ,
  592.                  character'val( char2 ) ,
  593.                  character'val( char3 ) ) ;
  594.     end file_out ;
  595.      
  596.     Procedure z_file_out(char1 : in character ; 
  597.                          char2 : in character := ascii.nul ;
  598.                          char3 : in character := ascii.nul ) is
  599.       -- same as file_out but does not try to fix Telesoft Problems
  600.       -- the following code required by wicat...
  601.       -- This is used exclusively for transmitting escape sequences to 
  602.       -- output devices
  603.       c1 , c2 , c3 : character ;
  604.     begin -- z_file_out
  605.       -- we also know where_to = to_file or something...
  606.       c1 := bobs_convert ( character'pos(char1) + 128 ) ;
  607.       formatter_io.put( ot_file , c1 ) ;
  608.       if char2 /= ascii.nul then
  609.         c2 := bobs_convert ( character'pos(char2) + 128 ) ;
  610.         formatter_io.put( ot_file , c2 ) ;
  611.         if char3 /= ascii.nul then
  612.           c3 := bobs_convert ( character'pos(char3) + 128 ) ;
  613.           formatter_io.put( ot_file , c3 ) ;
  614.         end if ;
  615.       end if ;
  616.     end z_file_out ;
  617.      
  618.     procedure end_dumb_output_line is
  619.       -- end an output line to a "dumb" device
  620.     begin -- end_dumb_output_line
  621.       formatter_io.new_line( ot_file ) ;
  622.     end end_dumb_output_line ;
  623.      
  624.     Procedure otsxy( x , y : in integer ; s : in string) is
  625.     begin
  626.       crt_windows.goto_line_column( master_window , y , x ) ;
  627.       crt_windows.put(s) ;
  628.     end otsxy ;
  629.       
  630.     Procedure otnxy( x , y , n : in integer ; len : in integer := 1 ) is
  631.     begin
  632.       crt_windows.goto_line_column( master_window , y , x ) ;
  633.       put(n , len ) ;
  634.     end otnxy ;
  635.       
  636.     Function Stall ( done_on_q : in boolean ) return boolean is
  637.       chr : character ;
  638.       done : boolean  ;
  639.     begin
  640.       clear_end_of_screen ( master_window , 22 , 1 ) ;
  641.       otsxy(10,22,"Type <space> to continue...") ;
  642.       if done_on_q then
  643.         otsxy(10,23,"Type 'Q' to Quit Listing...") ;
  644.       end if ;
  645.       bell ;
  646.       chr := char_within_range_or_abort ( ascii.nul , ascii.nul , ascii.del ) ;
  647.       done := ( (chr = 'q') or (chr = 'Q') ) and done_on_q ;
  648.       if done then
  649.         clear_end_of_screen ( master_window , 22 , 1 ) ;
  650.       else
  651.         clear_window ( master_window ) ;
  652.         clear_prompt ( master_window ) ;
  653.       end if ;
  654.       return done ;
  655.     end stall ;
  656.      
  657.     Procedure change_printer( new_printer : in printer_type ) is
  658.     begin
  659.       current_environment.printer_brand := new_printer ;
  660.       -- first set z_printer
  661.       z_printer := new_printer ;
  662.       -- then, deal with idiosyncrasies of printers
  663.       if z_printer = z_cent737 then
  664.         printer_points_per_inch := 150 ;
  665.       --###--RSC02 start
  666.       else
  667.         printer_points_per_inch := 120 ; -- for the qume/diablo prop
  668.       end if ;
  669.       printer_vertical_per_inch := 48 ;
  670.       z_forward := z_printer = z_cent737 ;      --just a forward printer
  671.       if z_printer = z_cent737 then
  672.         z_proportional := z_p_centronics ;
  673.       elsif z_printer = z_qume then
  674.         z_proportional := z_p_qume ;
  675.       else
  676.         z_proportional := z_p_diablo ;
  677.       end if ;
  678.       --###--RSC02 end
  679.       if z_printer = z_pdumb then
  680.         z_smart_printer := z_dumb ;
  681.       elsif z_printer = z_pbackspace 
  682.          or z_printer = z_la100draft 
  683.          or z_printer = z_la100medium 
  684.          or z_printer = z_la100high then
  685.         z_smart_printer := z_backspace ;
  686.       else
  687.         z_smart_printer := z_smart ;
  688.       end if ;
  689.       we_have_single_tray_loader := printer_accessories = trayloader ;
  690.       we_have_dual_tray_loader   := printer_accessories = dual_tray  ;
  691.       we_have_some_tray_loader   := we_have_single_tray_loader
  692.                                  or we_have_dual_tray_loader         ;
  693.     end change_printer;
  694.      
  695.     Function Odd ( I : Integer ) return boolean is
  696.     begin -- odd
  697.       return i mod 2 = 1 ;
  698.     end odd ;
  699.      
  700.     procedure Printer_Globals_initialize is
  701.      
  702.     begin -- Printer_Globals_initialize 
  703.       master_window := create_window ( 1 , basic_io_system.total_crt_col ,
  704.                                        1 , basic_io_system.total_crt_line ,
  705.                                        true , 1 ) ;
  706.       -- Create a screen window
  707.       -- Make the window the entire screen, with a 1 line status area
  708.       -- at the top of the window
  709.       set_current_window ( master_window ) ;
  710.       clear_prompt( master_window ) ;
  711.       clear_window( master_window ) ;
  712.       default_font.name  := "12 Pitch                 " ;
  713.       default_font.number:= 0                           ;
  714.       default_font.vertical_points_per_inch   := 48     ;
  715.       default_font.horizontal_points_per_inch := 120    ;
  716.       default_font.Font_width := 10 ; 
  717.       default_font.Font_height := 8 ;
  718.       default_font.mappings_necessary := false          ;
  719.       for posn in extended_character loop
  720.         default_font.width           (posn)   := horizontal_measurement(10);
  721.         default_font.hammer_intensity(posn)   :=  1 ;
  722.         default_font.map_string      (posn) (1) := posn ;
  723.         for inside in 2 .. a_map_string'last loop
  724.           default_font.map_string    (posn) (inside) := 0    ;
  725.         end loop ;
  726.       end loop ;
  727.       current_font := default_font ;
  728.       Space_Width         := default_font.width( extended_space ) ;
  729.       Half_Space_Width    := Space_Width / 2 ;
  730.       permanent_font := default_font ;
  731.       temporary_font := default_font ;
  732.     end Printer_Globals_initialize ;
  733.      
  734.     Procedure UpDate_Status is
  735.     begin
  736.       If Initial_Environment.Show_Output_Status
  737.       and then Initial_Environment.Where_To /= To_Screen then
  738.         set_reverse(true);
  739.         -- unchanging ... otsxy( 39 ,  2 , ' ' & Main_In_File_Name & ' ' ) ;
  740.         otsxy( 39 ,  4 , ' ' & Alt_In_File_Name & ' '       ) ;
  741.         -- the alt in file name is set within PRNTCMD1
  742.         -- unchanging ... otsxy( 39 ,  6 , ' ' & Var_In_File_Name & ' '  ) ;
  743.         -- also, line 6 could be an index file name
  744.         -- and is set inside PRNTCMD1
  745.         -- unchanging ... otsxy( 39 ,  8 , ' ' & Ot_File_Name & ' '      ) ;
  746.         -- copy , current page , input , output 
  747.         -- In Initialize ... otnxy( 39 , 10 , ' ' & Copy # & ' ' , 10    ) ;
  748.         otnxy( 39 , 12 , Physical_Page_Number  , 10               ) ;
  749.         put ( " " ) ;
  750.         -- page number also updated by prntout2
  751.         otnxy( 39 , 14 , Physical_Input_Lines  , 10               ) ;
  752.         put ( " " ) ;
  753.         otnxy( 39 , 16 , Physical_Output_Lines , 10               ) ;
  754.         put ( " " ) ;
  755.         set_reverse(false);
  756.         goto_line_column( master_window , 1 , 1 ) ;
  757.       end if ;
  758.     end UpDate_Status ;
  759.    
  760.     procedure initialize_Printer_Globals_for_a_new_document is
  761.     begin -- initialize_printer_globals_for_a_new_document
  762.       Physical_Page_Number  := 1 ;
  763.       Physical_Input_Lines  := 1 ;
  764.       Physical_Output_Lines := 0 ;
  765.       If Initial_Environment.Show_Output_Status
  766.       and then Initial_Environment.Where_To /= To_Screen then
  767.         if copies_printed_so_far = 0 then
  768.           clear_prompt( master_window ) ;
  769.           clear_window( master_window ) ;
  770.           goto_prompt_line_column ( master_window , 1 , 14 ) ;
  771.           put (           "E X E C U T I N G   W O R D   P R O C E S S O R");
  772.           otsxy( 15 ,  2 , "Main File Title"      ) ;
  773.           otsxy( 15 ,  4 , "Included File Title"  ) ;
  774.           otsxy( 15 ,  6 , "Variable File Title"  ) ;
  775.           otsxy( 15 ,  8 , "Output File Title"    ) ;
  776.           otsxy( 15 , 10 , "Current Copy Number"  ) ;
  777.           otsxy( 15 , 12 , "Current Page Number"  ) ;
  778.           otsxy( 15 , 14 , "Current Input Line"   ) ;
  779.           otsxy( 15 , 16 , "Total Output Lines"   ) ;
  780.           -- now, put in permanent lines...
  781.           set_reverse(true);
  782.           otsxy( 39 ,  2 , ' ' & Main_In_File_Name & ' '     ) ;
  783.           otsxy( 39 ,  6 , ' ' & Var_In_File_Name  & ' '     ) ;
  784.           otsxy( 39 ,  8 , ' ' & Ot_File_Name      & ' '     ) ;
  785.           otnxy( 39 , 10 , 1 , 10                 ) ;
  786.           put( " " ) ;
  787.           set_reverse(false);
  788.         else
  789.           -- new copy
  790.           set_reverse ( true ) ;
  791.           otnxy( 39 , 10 , copies_printed_so_far+1, 10 ) ;
  792.           put ( " " ) ;
  793.           set_reverse ( false ) ;
  794.         end if ;
  795.         update_status ;
  796.       end if ;
  797.     end initialize_Printer_Globals_for_a_new_document ;
  798.    
  799.     procedure finish_Printer_Globals_for_an_old_document    is
  800.     begin -- finish_Printer_Globals_for_an_old_document 
  801.       null ;
  802.     end finish_Printer_Globals_for_an_old_document ;
  803.     
  804.     procedure close_Printer_Globals is
  805.     begin -- close_Printer_Globals
  806.       null ;
  807.     end close_Printer_Globals ;
  808.      
  809.   begin -- printer_globals
  810.     Printer_Globals_initialize ;
  811.   end printer_globals ;
  812.  
  813.   --$$$- PRNTGLOB
  814.  
  815. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  816. --nametree
  817. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  818.  
  819.   --$$$+ NAMETREE
  820.     
  821.   --
  822.   -- File 0xx
  823.   --
  824.   -- Formatter Written By Robert S. Cymbalski
  825.   --                      Science Applications International Corporation
  826.   --                      Energy Systems Group
  827.   --                      Ada Software Development Project Team
  828.   --                      2280 U.S. Highway 19 North, Suite 120
  829.   --                      Clearwater, Florida  33575
  830.   --
  831.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  832.   --
  833.    
  834.   with string_library  ;
  835.   use  string_library  ;
  836.     
  837.   with crt_windows     ;
  838.   use  crt_windows     ;
  839.     
  840.   with Wordp_Globals   ;
  841.   use  Wordp_Globals   ;
  842.   
  843.   Package NAME_TREE is
  844.     
  845.     type Text_Formatter_Command is ( illegal_command , add_command ,
  846.                                    backward_add_command , binding_command ,
  847.                                    bold_command , center_command ,
  848.                                    char_spacing_command , char_width_command ,
  849.                                    comments_command , date_dmy_command ,
  850.                                    date_mdy_command , date_slash_command ,
  851.                                    date_dash_command , date_ymd_command ,
  852.                                    dot_lead_command , lcrm_command ,
  853.                                    rclm_command , else_command ,
  854.                                    end_page_command , envelope_feed_command ,
  855.                                    fancy_print_command , fill_command ,
  856.                                    finish_command , footers_command ,
  857.                                    footnote_command , forward_printing_command ,
  858.                                    go_left_command , headers_command ,
  859.                                    head_foot_space_command , hypen_command ,
  860.                                    if_command ,
  861.                                    ifswitch_command , indent_command ,
  862.                                    indent_neg_command , index_command ,
  863.                                    indexfile_command , insert_command ,
  864.                                    justify_margins_command ,
  865.                                    justify_numbers_command ,
  866.                                    justify_rtmargin_command ,
  867.                                    same_line_command , line_save_command ,
  868.                                    mult_line_spacing_command , 
  869.                                    vert_line_spacing_command ,
  870.                                    bottom_margin_command , left_margin_command ,
  871.                                    right_margin_command , top_margin_command ,
  872.                                    page_numbering_command ,
  873.                                    section_page_numbering_command ,
  874.                                    paper_length_command , paper_width_command ,
  875.                                    para_indent_command , new_para_command ,
  876.                                    pause_command , printer_control_command ,
  877.                                    read_command , ribbon_color_command ,
  878.                                    shadow_printing_command ,
  879.                                    prop_spacing_command , subpara_command ,
  880.                                    switch_command , tabs_command ,
  881.                                    tabs_vertical_command ,
  882.                                    underline_chars_command ,
  883.                                    underline_cont_command ,
  884.                                    underscore_command ,
  885.                                    variable_data_command ,
  886.                                    write_command , 
  887.                                    -- now, we have character setting commands
  888.                                    subscript_command               , 
  889.                                    superscript_command             ,
  890.                                    underline_foothead_command      ,
  891.                                    underline_character_command     ,
  892.                                    ucontinuous_character_command   ,
  893.                                    bold_character_command          ,
  894.                                    shadow_character_command        ,
  895.                                    temporary_font_character_command,
  896.                                    forced_space_character_command  ,
  897.                                    --
  898.                                    user_defined_command ) ;
  899.  
  900.     a_tree_name_string_length : constant integer := 25 ;
  901.      
  902.     subtype a_tree_name_string is string ( 1 .. a_tree_name_string_length ) ;
  903.      
  904.     type NODE_TYPE ;
  905.       
  906.     type NAME_NODE is access node_type ;
  907.       
  908.     type NODE_TYPE is
  909.       record
  910.         name : a_tree_name_string ;
  911.         printer_command : Text_Formatter_Command ;
  912.         other_info : integer ;
  913.         left_son : name_node ;
  914.         right_son : name_node ;
  915.       end record ;
  916.         
  917.     blank_tree_name_string  : constant a_tree_name_string 
  918.                                            := "                         " ;
  919.     illegal_node : constant name_node := null ;
  920.     empty_node   : constant node_type 
  921.                        := (blank_tree_name_string,illegal_command,0,null,null) ;
  922.      
  923.     last_good_command : a_tree_name_string ;
  924.      
  925.     Procedure INSERT_NAME( orig_name: in string ;
  926.                            new_printer_command : in Text_Formatter_Command ;
  927.                            new_info : in integer ;
  928.                            startnode : in out name_node ;
  929.                            case_sensitive : boolean := false ) ;
  930.       -- insert the new name into the tree structure
  931.         
  932.     Procedure DELETE_NAME ( del_name : in string ; 
  933.                             startnode : in out name_node ) ;
  934.       -- delete the given name from the tree
  935.         
  936.     Function QUERY ( search_name       : in a_tree_name_string ;
  937.                      startnode         : in name_node          ;
  938.                      case_sensitive    : in boolean := false   )
  939.                      return name_node ;
  940.       -- search for given name in tree structure and if found return
  941.       -- the information on it
  942.         
  943.   end ;
  944.     
  945.   Package body NAME_TREE is
  946.     
  947.     Procedure MAP_UP( name : in out string ) is
  948.       map_up_length : integer := name'length ;
  949.     begin
  950.       for i in 1 .. map_up_length loop
  951.         if name(i) >= 'a' and name(i) <= 'z' then
  952.           name(i) := character'val(character'pos(name(i)) - 32 ) ;
  953.         end if ;
  954.       end loop ;
  955.     end ;
  956.       
  957.     Procedure INSERT_NAME( orig_name: in string ;
  958.                            new_printer_command : in Text_Formatter_Command ;
  959.                            new_info : in integer ;
  960.                            startnode : in out name_node ;
  961.                            case_sensitive : boolean := false ) is
  962.       new_node : name_node ;
  963.       name_len : constant integer := orig_name'length ;
  964.       new_name : string ( 1 .. name_len ) := orig_name ;
  965.     begin
  966.       if not case_sensitive then
  967.         map_up ( new_name ) ;
  968.       end if ;
  969.       if startnode = null then
  970.         new_node := new node_type ;
  971.         for i in 1 .. name_len loop
  972.           new_node.name(i) := new_name(i) ;
  973.         end loop ;
  974.         for i in name_len+1 .. 25 loop 
  975.           new_node.name(i) := ' ' ;
  976.         end loop ;
  977.         new_node.left_son := null ;
  978.         new_node.right_son := null ;
  979.         new_node.other_info := new_info ;
  980.         new_node.printer_command := new_printer_command ;
  981.         startnode := new_node ;
  982.       elsif new_name(1 .. name_len) < startnode.name(1 .. name_len) then
  983.         INSERT_NAME( new_name , new_printer_command , new_info , 
  984.                                                            startnode.left_son );
  985.       elsif new_name(1 .. name_len) > startnode.name(1 .. name_len) then
  986.         INSERT_NAME( new_name , new_printer_command , new_info , 
  987.                                                           startnode.right_son );
  988.       else 
  989.         error(" Error - """ & compress(new_name) & """ is already in tree" ,
  990.               not_fatal_error , operator_wait , short_beep ) ;
  991.       end if ;
  992.     end INSERT_NAME ;
  993.       
  994.     Procedure DELETE_NAME ( del_name : in string ; 
  995.                             startnode : in out name_node ) is
  996.         
  997.       new_start : name_node ;
  998.       parent_new_start : name_node ;
  999.       name_len : integer := del_name'length ;
  1000.         
  1001.       Procedure FINDMIN( startnode : in out name_node ;
  1002.                          parent_min_node  : out name_node ) is
  1003.         new_node : name_node ;
  1004.       begin
  1005.         new_node := startnode ;
  1006.         while new_node.left_son.left_son /= null loop
  1007.           new_node := new_node.left_son ;
  1008.         end loop ;
  1009.         parent_min_node := new_node ;
  1010.       end ;
  1011.         
  1012.     begin
  1013.       if startnode /= null then
  1014.         if del_name(1 .. name_len) < startnode.name(1 .. name_len) then
  1015.           DELETE_NAME( del_name , startnode.left_son ) ;
  1016.         elsif  del_name(1 .. name_len) > startnode.name(1 .. name_len) then
  1017.           DELETE_NAME( del_name , startnode.right_son ) ;
  1018.         elsif (startnode.left_son = null) and (startnode.right_son = null) then
  1019.         -- get here when startnode contains del_name
  1020.           -- dispose the node holding del_name and assign the value null
  1021.           startnode := null ;
  1022.         elsif startnode.left_son = null then
  1023.           -- dispose of the node holding del_name and
  1024.           -- move right son up  position del_name node held
  1025.           startnode := startnode.right_son ;
  1026.         elsif startnode.right_son = null then
  1027.           -- dispose of the node holding del_name and
  1028.           -- move left son up to position del_name node held
  1029.           startnode := startnode.left_son ;
  1030.         else 
  1031.           -- both children are present 
  1032.           if startnode.right_son.left_son = null then
  1033.             startnode.right_son.left_son := startnode.left_son ;
  1034.             startnode := startnode.right_son ;
  1035.           else
  1036.             FINDMIN( startnode.right_son , parent_new_start ) ;
  1037.             new_start := parent_new_start.left_son ;
  1038.             new_start.left_son := startnode.left_son ;
  1039.             parent_new_start.left_son := new_start.right_son ;
  1040.             new_start.right_son := startnode.right_son ;
  1041.             startnode := new_start ;
  1042.           end if ;
  1043.         end if ;
  1044.       else
  1045.         -- startnode = null ; name to delete most not have 
  1046.         -- been in the tree
  1047.         error(" Error - """ & compress(del_name) &
  1048.                           """ was not in tree! Not Del",
  1049.                    not_fatal_error , operator_wait , short_beep ) ;
  1050.       end if ;
  1051.     end DELETE_NAME ;
  1052.      
  1053.     Function QUERY ( search_name       : in a_tree_name_string ;
  1054.                      startnode         : in name_node          ;
  1055.                      case_sensitive    : in boolean := false   )
  1056.                      return name_node is
  1057.       -- search for given name in tree structure and if found return
  1058.       -- the information on it
  1059.       -- for now, we ignore case_sensitive and assume that the
  1060.       -- tree is upper case, and we map search_name to upper case
  1061.       s_name_len       : integer            ;
  1062.       case_search_name : a_tree_name_string := search_name ;
  1063.       cur_node         : name_node          ;
  1064.     begin
  1065.       if startnode = null then 
  1066.         return illegal_node ;
  1067.       else
  1068.         cur_node := startnode ;
  1069.         if not case_sensitive then
  1070.           map_up(case_search_name);
  1071.         end if ;
  1072.         -- now, find length for compare...
  1073.         s_name_len := position( ' ' , case_search_name ) ;
  1074.         if s_name_len = 0 then
  1075.           -- no space in the name...
  1076.           s_name_len := a_tree_name_string'length ;
  1077.         else
  1078.           s_name_len := s_name_len - 1 ; -- because space does not count...
  1079.           if s_name_len = 0 then
  1080.             -- blank name sent over
  1081.             return illegal_node ;
  1082.           elsif s_name_len < 3 then
  1083.             s_name_len := 3 ;           -- to force it to compare spaces...
  1084.           end if ;
  1085.         end if ;
  1086.         -- time to work it...
  1087.         loop
  1088.           if case_search_name ( 1 .. s_name_len ) 
  1089.               = cur_node.name ( 1 .. s_name_len ) then
  1090.             -- found it...
  1091.             last_good_command := cur_node.name ; -- for others to use...
  1092.             return cur_node ;
  1093.           elsif case_search_name ( 1 .. s_name_len ) 
  1094.                  < cur_node.name ( 1 .. s_name_len ) then
  1095.             -- is to the left of current
  1096.             cur_node := cur_node.left_son ;
  1097.           else
  1098.             -- is to the right of current
  1099.             cur_node := cur_node.right_son ;
  1100.           end if ;
  1101.           if cur_node = null then
  1102.             -- not found
  1103.             -- try to make it shorter and try again...
  1104.             if s_name_len > 3 then
  1105.               -- try abbreviation
  1106.               case_search_name ( s_name_len ) := ' ' ;
  1107.               return query ( case_search_name , startnode , case_sensitive ) ;
  1108.             else
  1109.               return illegal_node ; -- not found...
  1110.             end if ;
  1111.           end if ;
  1112.         end loop ;
  1113.       end if ;
  1114.     end query ;
  1115.       
  1116.   begin -- NAME_TREE
  1117.     -- 
  1118.     null ;
  1119.     -- 
  1120.   end NAME_TREE ;
  1121.     
  1122.   --$$$- NAMETREE
  1123.  
  1124. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1125. --printf
  1126. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1127.  
  1128.   --$$$+ PRINTF
  1129.  
  1130.   --
  1131.   -- File 0xx
  1132.   --
  1133.   -- Formatter Written By Robert S. Cymbalski
  1134.   --                      Science Applications International Corporation
  1135.   --                      Energy Systems Group
  1136.   --                      Ada Software Development Project Team
  1137.   --                      2280 U.S. Highway 19 North, Suite 120
  1138.   --                      Clearwater, Florida  33575
  1139.   --
  1140.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  1141.   --
  1142.    
  1143.   with string_library  ;
  1144.   use  string_library  ;
  1145.    
  1146.   with Wordp_Globals   ;
  1147.   use  Wordp_Globals   ;
  1148.  
  1149.   with printer_globals ;
  1150.   use  printer_globals ;
  1151.     
  1152.   Package Printf is
  1153.     
  1154.     current_vertical_motion_index     : vertical_measurement   :=  8 ;
  1155.     current_horizontal_motion_index   : horizontal_measurement := 10 ;
  1156.     current_printer_direction_Forward : boolean  := true             ;
  1157.     current_print_font                : Font_Number := 0 ;
  1158.       -- 0 means that font has not yet been set
  1159.     Binding_Edge_Amount               : horizontal_measurement       ;
  1160.      
  1161.     type type_ribbon_color          is ( ribbon_unknown ,
  1162.                                          ribbon_red ,
  1163.                                          ribbon_black ) ;
  1164.       
  1165.     current_ribbon_color            : type_ribbon_color := ribbon_unknown ;
  1166.       
  1167.     -- the list of commands which we might issue to a printer...
  1168.     type printer_command_type is ( set_hmi , abs_hor_tab , graphics_on ,
  1169.                                  graphics_off , set_subscript ,
  1170.                                  set_superscript , move_prop_points ,
  1171.                                  dont_move , set_vmi , set_red_ribbon ,
  1172.                                  set_black_ribbon , set_proportional  ,
  1173.                                  set_non_proportional , set_form_length , 
  1174.                                  set_print_forward , set_print_backward , 
  1175.                                  go_up_on_page , printer_reset , 
  1176.                                  absolute_point_tab ,
  1177.                                  Underline_On , Underline_Off ,
  1178.                                  Bold_On , Bold_Off ,
  1179.                                  Shadow_On , Shadow_Off ,
  1180.                                  set_font_number ,
  1181.                                  print_special_spoke_2 , print_special_spoke_4 ,
  1182.                                  start_first_page , 
  1183.                                  end_page_start_another , start_middle_page , 
  1184.                                  end_last_page , start_envelope
  1185.                                ) ;
  1186.       
  1187.     Procedure delay_printer ;
  1188.       
  1189.     Procedure execute_printer_command(
  1190.                                 new_print_command : in printer_command_type ;
  1191.                                 param             : in integer := 0     ) ;
  1192.     
  1193.   end ;
  1194.     
  1195.   Package body Printf is
  1196.     
  1197.     Procedure delay_printer is
  1198.     begin
  1199.       for looper in 1 .. 30 loop
  1200.         file_out(ascii.nul) ;
  1201.       end loop;
  1202.     end delay_printer ;
  1203.      
  1204.     Procedure execute_printer_command(
  1205.                                 new_print_command : in printer_command_type ;
  1206.                                 param             : in integer := 0     ) is
  1207.      Fparm : integer := param ;
  1208.     
  1209.       Procedure do_errors is
  1210.         err_str : pstring ;
  1211.       begin
  1212.         err_str := "Program Error : Printf called with "
  1213.                     & int_to_str ( printer_command_type'pos(new_print_command) )
  1214.                     & "/" & int_to_str( Fparm ) ;
  1215.         error(err_str , not_fatal_error , operator_wait , short_beep ) ;
  1216.       end do_errors ;
  1217.       
  1218.       --###--RSC02
  1219.        
  1220.       Procedure Tab_To_Absolute_Horizontal_Position 
  1221.                         ( Destination             : Horizontal_Measurement ) is 
  1222.         actual_destination : horizontal_measurement := destination ;
  1223.         Col_To_Move_To       : Integer ;
  1224.         Points_To_Move_Extra : Integer ;
  1225.         Old_HMI              : Horizontal_Measurement 
  1226.                                 := current_horizontal_motion_index ;
  1227.         new_hmi              : horizontal_measurement ;
  1228.         old_forward          : boolean := current_printer_direction_forward ;
  1229.       begin
  1230. -- put( "Destination => " ) ;
  1231. -- put( destination                            , 5 ) ; put ( ascii.cr ) ;
  1232. -- put( "HMI         => " ) ;
  1233. -- put( current_horizontal_motion_index        , 5 ) ; put ( ascii.cr ) ;
  1234.         If Binding_Edge_Amount /= 0
  1235.         and then odd ( Physical_Page_Number ) then
  1236.           Actual_Destination := Actual_Destination + Binding_Edge_Amount ;
  1237.         end if ;
  1238.         if z_proportional = z_p_centronics then
  1239.           z_file_out ( ascii.cr ) ;
  1240.           execute_printer_command ( move_prop_points , Actual_Destination ) ;
  1241.         else
  1242.           Col_To_Move_To       := Actual_Destination 
  1243.                                              / current_horizontal_motion_index ;
  1244.           Points_To_Move_Extra := Actual_Destination 
  1245.                                            mod Current_Horizontal_Motion_Index ;
  1246.           if col_to_move_to > 126 then
  1247.             -- we have to be tricky.....
  1248. -- put("##################################");          put ( ascii.cr ) ;
  1249. -- put( "To Col      => " ) ;
  1250. -- put( col_to_move_to                         , 5 ) ; put ( ascii.cr ) ;
  1251. -- put( "Plus Points => " ) ;
  1252. -- put( points_to_move_extra                   , 5 ) ; put ( ascii.cr ) ;
  1253. -- put("##################################");          put ( ascii.cr ) ;
  1254.             if col_to_move_to < 250 then
  1255.               new_hmi := old_hmi + old_hmi ;
  1256.             elsif col_to_move_to < 375 then
  1257.               new_hmi := old_hmi + old_hmi + old_hmi ;
  1258.             else
  1259.               -- that gives 25" and our max allowed anyway is 14"
  1260.               new_hmi := printer_points_per_inch / 5 ;
  1261.             end if ;
  1262.             execute_printer_command ( set_hmi , new_hmi ) ;
  1263.             if not current_printer_direction_forward then
  1264.               execute_printer_command ( set_print_forward ) ;
  1265.             end if ;
  1266.             Col_To_Move_To       := Actual_Destination  /  new_hmi ;
  1267.             Points_To_Move_Extra := Actual_Destination mod new_hmi ;
  1268.           end if ;
  1269. -- put( "To Col      => " ) ;
  1270. -- put( col_to_move_to                         , 5 ) ; put ( ascii.cr ) ;
  1271. -- put( "Plus Points => " ) ;
  1272. -- put( points_to_move_extra                   , 5 ) ; put ( ascii.cr ) ;
  1273. -- if current_printer_direction_forward then
  1274. -- put( "Forward     => " ) ; put ( ascii.cr ) ;
  1275. -- else
  1276. -- put( "Backward    => " ) ; put ( ascii.cr ) ;
  1277. -- end if ;
  1278.           if ( not Current_Printer_Direction_Forward ) 
  1279.           and then ( Points_To_Move_Extra /= 0 ) then
  1280.             Col_To_Move_To       := Col_To_Move_To + 1 ;
  1281.             Points_To_Move_Extra := Current_Horizontal_Motion_Index 
  1282.                                                         - Points_To_Move_Extra ;
  1283. -- put( "To Col      => " ) ;
  1284. -- put( col_to_move_to                         , 5 ) ; put ( ascii.cr ) ;
  1285. -- put( "Plus Points => " ) ;
  1286. -- put( points_to_move_extra                   , 5 ) ; put ( ascii.cr ) ;
  1287.           end if ;
  1288.           execute_printer_command ( abs_hor_tab , Col_To_Move_To ) ;  
  1289.           -- Jump to the column -- and then take care of the rest
  1290.           if Points_To_Move_Extra > 0 then
  1291.             -- must take care of leftovers
  1292.             if z_proportional = z_p_qume then
  1293.               execute_printer_command ( set_non_proportional ) ;
  1294.             end if ;
  1295.             execute_printer_command ( set_hmi , Points_To_Move_Extra ) ;
  1296.             z_file_out ( ' ' ) ;
  1297.             if z_proportional = z_p_qume then
  1298.               execute_printer_command ( set_proportional ) ;
  1299.             end if ;
  1300.           end if ;
  1301.           -- here, the hmi could have been changed by either of two actions
  1302.           if old_hmi /= current_horizontal_motion_index then
  1303.             execute_printer_command ( set_hmi , old_hmi ) ;
  1304.           end if ;
  1305.           if old_forward /= current_printer_direction_forward then
  1306.             -- can only get here if we changed backwards to forward, so
  1307.             -- simply switch back...
  1308.             execute_printer_command ( set_print_backward ) ;
  1309.           end if ;
  1310.         end if;
  1311.       end Tab_To_Absolute_Horizontal_Position ;
  1312.      
  1313.       Procedure do_qume is
  1314.         cc : character ;
  1315.       begin
  1316.         case new_print_command is
  1317.           when set_hmi                => z_file_out(ascii.esc , 
  1318.                                                character'val(31) ,
  1319.                                                character'val(Fparm + 1) ) ;
  1320.           when abs_hor_tab            => z_file_out(ascii.esc , ascii.ht  ,
  1321.                                                character'val(Fparm + 1) ) ;
  1322.           when absolute_point_tab     => Tab_To_Absolute_Horizontal_Position ( 
  1323.                                                                        Fparm ) ;
  1324.           when graphics_on            => z_file_out(ascii.esc,'3') ;
  1325.           when graphics_off           => z_file_out(ascii.esc,'4') ;
  1326.           when set_subscript          => z_file_out(ascii.esc,'U') ;
  1327.           when set_superscript        => z_file_out(ascii.esc,'D') ;
  1328.           when move_prop_points       => while Fparm > 50 loop
  1329.                                            z_file_out(character'val(31) ,
  1330.                                                character'val(50) ) ;
  1331.                                            Fparm := Fparm - 50 ;
  1332.                                          end loop ;
  1333.                                          z_file_out(character'val(31) ,
  1334.                                              character'val(Fparm) ) ;
  1335.           when dont_move              => z_file_out(character'val(31) , 'A' ) ;
  1336.           when set_vmi                => z_file_out(ascii.esc ,
  1337.                                                character'val(30) ,
  1338.                                                character'val(Fparm + 1) ) ;
  1339.           when set_red_ribbon         => z_file_out(ascii.esc ,'A') ;
  1340.           when set_black_ribbon       => z_file_out(ascii.esc ,'B') ;
  1341.           when set_proportional       => null ;   -- z_file_out(ascii.esc , 
  1342.                                                   -- character'val(14));
  1343.           when set_non_proportional   => null ;   -- z_file_out(ascii.esc ,
  1344.                                                   -- character'val(15));
  1345.           when set_form_length        => if z_printer=z_qume then
  1346.                                            if we_have_some_tray_loader then
  1347.                                             Fparm := Fparm+48; 
  1348.                                                             --add 1inch for tray
  1349.                                            end if ;
  1350.                                          end if ;
  1351.                                          Fparm := Fparm / 8 ;
  1352.                                          if z_printer = z_citoh then
  1353.                                            if Fparm > 66 then
  1354.                                              Fparm := 66 ;
  1355.                                            end if ;
  1356.                                          end if ;
  1357.                                          cc := character'val(48+(Fparm mod 10));
  1358.                                          -- '0' + last digit
  1359.                                          Fparm := Fparm / 10 ;
  1360.                                          if Fparm < 10 then
  1361.                                            Fparm := Fparm + 48 ;
  1362.                                          else
  1363.                                            Fparm := Fparm + 55 ; -- so 10 = 'A'
  1364.                                          end if ;
  1365.                                          delay_printer ; --for qume problem
  1366.                                          delay_printer ; --for qume problem
  1367.                                          z_file_out(ascii.esc) ;
  1368.                                          z_file_out('F',character'val(Fparm),
  1369.                                                      cc);
  1370.           when set_print_forward      => z_file_out(ascii.esc,'5') ;
  1371.           when set_print_backward     => z_file_out(ascii.esc,'6') ;
  1372.           when go_up_on_page          => -- go Fparm lines up fix for backslash
  1373.                                          for tmpvar in 1 .. (Fparm + 1) loop
  1374.                                            z_file_out(ascii.esc,ascii.lf) ;
  1375.                                          end loop ;
  1376.                                          delay_printer ;
  1377.                                          -- now do a positive line feed
  1378.                                          z_file_out(ascii.lf) ;
  1379.           when printer_reset          => -- delay_printer ;
  1380.                                          -- delay_printer ;
  1381.                                          -- z_file_out( ascii.esc ,
  1382.                                                 -- character'val(26) , 'I' ) ;
  1383.                                execute_printer_command( set_hmi , 12);
  1384.                                execute_printer_command( set_vmi ,  8);
  1385.                                execute_printer_command( set_black_ribbon  ) ;
  1386.                                execute_printer_command( set_print_forward ) ;
  1387.           when set_font_number        => null ;
  1388.           when print_special_spoke_2  => z_file_out(ascii.esc ,' ');
  1389.           when print_special_spoke_4  => z_file_out(ascii.esc ,'/');
  1390.           when start_first_page       => if (z_printer = z_citoh) 
  1391.                                          and then we_have_some_tray_loader then
  1392.                                            -- insert a page
  1393.                                            z_file_out(ascii.esc , 'M' ,'1') ;
  1394.                                          end if ;
  1395.           when end_page_start_another => z_file_out(ascii.ff) ;
  1396.                                          if z_printer = z_citoh 
  1397.                                          and then we_have_some_tray_loader then
  1398.                                            z_file_out(ascii.ff) ;
  1399.                                            -- to ensure it is ejected
  1400.                                            z_file_out(ascii.esc , 'M' , '2') ;
  1401.                                          end if ;
  1402.           when start_middle_page      => if z_printer = z_citoh 
  1403.                                          and then we_have_some_tray_loader then
  1404.                                            z_file_out(ascii.esc , 'M' , '2') ;
  1405.                                          end if ;
  1406.           when end_last_page          => z_file_out(ascii.ff);
  1407.                                          if z_printer = z_citoh 
  1408.                                          and then we_have_some_tray_loader then
  1409.                                            z_file_out(ascii.ff) ;
  1410.                                          end if ;
  1411.           when start_envelope         => z_file_out(ascii.ff) ;
  1412.                                          if z_printer = z_citoh 
  1413.                                          and then we_have_some_tray_loader then
  1414.                                            z_file_out(ascii.ff) ;
  1415.                                            z_file_out(ascii.esc , 'M' , '3') ;
  1416.                                          end if ;
  1417.           when others                 => do_errors ;
  1418.         end case ;
  1419.       end ;
  1420.         
  1421.       --###--RSC02
  1422.        
  1423.       Procedure do_xerox is
  1424.       begin
  1425.         case new_print_command is
  1426.           when set_hmi                => z_file_out(ascii.esc , 
  1427.                                                character'val(31) ,
  1428.                                                character'val(Fparm + 1) ) ;
  1429.           when abs_hor_tab            => z_file_out(ascii.esc , ascii.ht ,
  1430.                                                character'val(Fparm + 1) ) ;
  1431.           when absolute_point_tab     => Tab_To_Absolute_Horizontal_Position ( 
  1432.                                                                        Fparm ) ;
  1433.           when set_subscript          => z_file_out(ascii.esc ,'U') ;
  1434.           when set_superscript        => z_file_out(ascii.esc ,'D') ;
  1435.           when set_vmi                => z_file_out(ascii.esc ,
  1436.                                                character'val(30) ,
  1437.                                                character'val(Fparm + 1) ) ;
  1438.           when set_red_ribbon         => z_file_out(ascii.esc , 'A') ;
  1439.           when set_black_ribbon       => z_file_out(ascii.esc , 'B') ;
  1440.           when set_form_length        => if we_have_some_tray_loader then
  1441.                                            Fparm := Fparm+48; -- for tray
  1442.                                          end if ;
  1443.                                         z_file_out(ascii.esc , ascii.ff ,
  1444.                                               character'val(Fparm / 8));
  1445.           when set_print_forward      => z_file_out(ascii.esc , '5') ;
  1446.           when set_print_backward     => z_file_out(ascii.esc , '6') ;
  1447.           when go_up_on_page          => for tmpvar in 1 .. (Fparm + 1) loop
  1448.                                            z_file_out(ascii.esc) ;
  1449.                                            z_file_out(ascii.lf) ;
  1450.                                          end loop ;
  1451.                                          delay_printer ;
  1452.                                          -- now do a positive line feed
  1453.                                          z_file_out(ascii.lf) ;
  1454.           when printer_reset          => z_file_out( ascii.esc , '\' ) ;
  1455.           when set_font_number        => null ;
  1456.           when print_special_spoke_2  => z_file_out(ascii.esc ,'Y');
  1457.           when print_special_spoke_4  => z_file_out(ascii.esc ,'Z');
  1458.           when start_first_page       => null ;
  1459.           when end_page_start_another => z_file_out(ascii.ff) ;
  1460.           when start_middle_page      => null ;
  1461.           when end_last_page          => z_file_out(ascii.ff) ;
  1462.           when start_envelope         => null ;
  1463.           when others                 => do_errors ;
  1464.         end case ;
  1465.       end do_xerox ;
  1466.         
  1467.       Procedure do_cent737 is
  1468.         cc     : character ;
  1469.       begin
  1470.         case new_print_command is
  1471.           when set_subscript          => z_file_out(ascii.esc, 
  1472.                                                   character'val(28)) ;
  1473.           when set_superscript        => z_file_out(ascii.esc,
  1474.                                                   character'val(30)) ;
  1475.           when absolute_point_tab     => Tab_To_Absolute_Horizontal_Position ( 
  1476.                                                                        Fparm ) ;
  1477.           when move_prop_points       => while Fparm >= 6 loop
  1478.                                            z_file_out( ascii.esc , 
  1479.                                                              character'val(6)) ;
  1480.                                            Fparm := Fparm - 6 ;
  1481.                                          end loop ;
  1482.                                          if Fparm > 0 then
  1483.                                            z_file_out(ascii.esc , 
  1484.                                                character'val(Fparm)) ;
  1485.                                          end if ;
  1486.           when set_proportional       => if (Fparm = 6) or (Fparm = 0) then
  1487.                                            cc := character'val(19) ;
  1488.                                          elsif Fparm = 7 then
  1489.                                            cc := character'val(20) ;
  1490.                                          elsif Fparm = 8 then
  1491.                                            cc := character'val(17) ;
  1492.                                          end if ;
  1493.                                          z_file_out(ascii.esc , cc ) ;
  1494.           when set_non_proportional => z_file_out(ascii.esc,character'val(19));
  1495.           when go_up_on_page          => for tmpvar in 1 .. (Fparm + 1) loop
  1496.                                            z_file_out(ascii.esc) ;
  1497.                                            z_file_out(ascii.lf) ;
  1498.                                          end loop ;
  1499.                                          delay_printer ;
  1500.                                          -- now do a positive line feed
  1501.                                          z_file_out(ascii.lf) ;
  1502.           when printer_reset          => z_file_out( ascii.esc ,
  1503.                                                 character'val(19) , 
  1504.                                                 character'val(13) ) ;
  1505.           when set_font_number        => null ;
  1506.           when print_special_spoke_2  => z_file_out(ascii.esc ,'\');
  1507.           when print_special_spoke_4  => z_file_out(ascii.esc ,'_');
  1508.           when start_first_page       => null ;
  1509.           when end_page_start_another => z_file_out(ascii.ff) ;
  1510.           when start_middle_page      => null ;
  1511.           when end_last_page          => z_file_out(ascii.ff) ;
  1512.           when start_envelope         => z_file_out(ascii.ff) ;
  1513.           when Underline_On           => z_file_out ( ascii.si ) ;
  1514.           when Underline_Off          => z_file_out ( ascii.so ) ;
  1515.           -- both bold and shadow are treated as bold 
  1516.           when Bold_On                => z_file_out ( ascii.esc , ascii.so ) ;
  1517.           when Bold_Off               => z_file_out ( ascii.esc , ascii.si ) ;
  1518.           when Shadow_On              => z_file_out ( ascii.esc , ascii.so ) ;
  1519.           when Shadow_Off             => z_file_out ( ascii.esc , ascii.si ) ;
  1520.           when others                 => do_errors ;
  1521.         end case ;
  1522.       end do_cent737 ;
  1523.         
  1524.       --###--RSC02
  1525.        
  1526.       Procedure do_dumb is
  1527.       begin
  1528.         null ;
  1529.       end do_dumb ;
  1530.         
  1531.       --###--RSC02
  1532.        
  1533.       procedure do_dataproducts is
  1534.       begin
  1535.         case new_print_command is
  1536.           when set_hmi                => z_file_out(ascii.esc , 
  1537.                                                character'val(31) ,
  1538.                                                character'val(Fparm + 1) ) ;
  1539.           when abs_hor_tab            => z_file_out(ascii.esc , ascii.ht ,
  1540.                                                character'val(Fparm + 1) ) ;
  1541.           when absolute_point_tab     => Tab_To_Absolute_Horizontal_Position ( 
  1542.                                                                        Fparm ) ;
  1543.           when set_subscript          => z_file_out(ascii.esc ,'U') ;
  1544.           when set_superscript        => z_file_out(ascii.esc ,'D') ;
  1545.           when set_vmi               => z_file_out(ascii.esc ,
  1546.                                                character'val(30) ,
  1547.                                                character'val(Fparm + 1) ) ;
  1548.           when set_red_ribbon         => z_file_out(ascii.esc , 'A') ;
  1549.           when set_black_ribbon       => z_file_out(ascii.esc , 'B') ;
  1550.           when set_form_length        => if we_have_some_tray_loader then
  1551.                                            Fparm := Fparm+48; --for tray
  1552.                                          end if ;
  1553.                                          z_file_out(ascii.esc , ascii.ff ,
  1554.                                                character'val(Fparm / 8)) ;
  1555.           when set_print_forward      => z_file_out(ascii.esc ,'5') ;
  1556.           when set_print_backward     => z_file_out(ascii.esc ,'6') ;
  1557.           when go_up_on_page          => for tmpvar in 1 .. (Fparm + 1) loop
  1558.                                            z_file_out(ascii.esc) ;
  1559.                                            z_file_out(ascii.lf) ;
  1560.                                          end loop ;
  1561.                                          delay_printer ;
  1562.                                          -- now do a positive line feed
  1563.                                          z_file_out(ascii.lf) ;
  1564.           when printer_reset          => delay_printer ;
  1565.                                          delay_printer ;
  1566.                                          z_file_out( ascii.esc ,
  1567.                                                 character'val(13) , 'P') ;
  1568.           when set_font_number        => null ;
  1569.           when print_special_spoke_2  => z_file_out(ascii.esc ,' ');
  1570.           when print_special_spoke_4  => z_file_out(ascii.esc ,
  1571.                                                   character'val(127));
  1572.           when start_first_page       => null ;
  1573.           when end_page_start_another => z_file_out(ascii.ff) ;
  1574.           when start_middle_page      => null ;
  1575.           when end_last_page          => z_file_out(ascii.ff) ;
  1576.           when start_envelope         => null ; 
  1577.           when others                 => do_errors ;
  1578.         end case ;
  1579.       end do_dataproducts ;
  1580.         
  1581.       --###--RSC02
  1582.  
  1583.     begin -- execute_printer_command
  1584.       --###--RSC02 starts
  1585.       case z_printer is
  1586.         when z_pdumb |
  1587.              z_pbackspace  => do_dumb ;
  1588.         when z_qume        => do_qume ;
  1589.         when z_xerox       => do_xerox ;
  1590.         when z_cent737     => do_cent737 ;
  1591.         when z_dataproducts=> do_dataproducts ;
  1592.         when z_unknown     => do_errors;
  1593.         when others        => do_errors ;
  1594.       end case ;
  1595.       --###--RSC02 ends
  1596.       case new_print_command is
  1597.         when set_hmi                => current_horizontal_motion_index
  1598.                                                       := Fparm ;
  1599.         when set_vmi                => current_vertical_motion_index
  1600.                                           := Fparm ;
  1601.         when set_red_ribbon         => current_ribbon_color := ribbon_red ;
  1602.         when set_black_ribbon       => current_ribbon_color := ribbon_black ;
  1603.         when set_print_forward      => current_printer_direction_Forward
  1604.                                                 := true ;
  1605.         when set_print_backward     => current_printer_direction_Forward
  1606.                                                 := false ;
  1607.         when set_font_number        => current_print_font := Fparm ;
  1608.         when others                 => null ;
  1609.       end case ;
  1610.     end execute_printer_command ;
  1611.       
  1612.   begin -- printf
  1613.     null ;
  1614.   end printf ;
  1615.  
  1616.   --$$$- PRINTF
  1617.  
  1618. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1619. --prntinot
  1620. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1621.  
  1622.   --$$$+ PRNTINOT
  1623.   
  1624.   --
  1625.   -- File 0xx
  1626.   --
  1627.   -- Formatter Written By Robert S. Cymbalski
  1628.   --                      Science Applications International Corporation
  1629.   --                      Ada Software Development Project Team
  1630.   --
  1631.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  1632.   --
  1633.     
  1634.   with string_library     ;
  1635.   use  string_library     ;
  1636.    
  1637.   with crt_windows        ;
  1638.   use  crt_windows        ;
  1639.    
  1640.   with printer_globals    ;
  1641.   use  printer_globals    ;
  1642.      
  1643.   with name_tree          ;  -- for command_error last_good_command
  1644.    
  1645.   Package print_in_to_out is
  1646.    
  1647.     -- This Package Is the Highest Output Device Dependent Package...
  1648.      
  1649.     -- The main goal of this package is to work with single lines and 
  1650.     -- move them to good output lines   ..
  1651.      
  1652.     max_characters_in_output_line : constant integer := 400 ;
  1653.      
  1654.     subtype output_line_index is integer 
  1655.                                  range 0 .. max_characters_in_output_line + 1 ;
  1656.      
  1657.     type charact_array is array ( output_line_index ) of extended_character ;
  1658.  
  1659.     cleared_char : constant charact_array :=
  1660.                  ( 0 .. max_characters_in_output_line + 1 =>  extended_space ) ;
  1661.      
  1662.     type measure_array is array ( output_line_index ) of horizontal_measurement;
  1663.          -- note that these measurement include any extra widths for
  1664.          -- shadow or double width etc...
  1665.  
  1666.     cleared_meas : constant measure_array :=
  1667.                            ( 0 .. max_characters_in_output_line + 1 =>  0 ) ;
  1668.      
  1669.     type boolean_array is array ( output_line_index ) of boolean   ;
  1670.  
  1671.     cleared_bool : constant boolean_array :=
  1672.                           ( 0 .. max_characters_in_output_line + 1 =>  false ) ;
  1673.      
  1674.     type up_or_down_position is ( superscript , normal , subscript ) ;
  1675.     ot_subscript      : constant up_or_down_position := subscript   ;
  1676.     ot_superscript    : constant up_or_down_position := superscript ;
  1677.  
  1678.     type updownp_array is array ( output_line_index ) of up_or_down_position ;
  1679.  
  1680.     cleared_updn : constant updownp_array :=
  1681.                          ( 0 .. max_characters_in_output_line + 1 =>  normal ) ;
  1682.      
  1683.     type font_nm_array is array ( output_line_index ) of font_number ;
  1684.  
  1685.     cleared_font : constant font_nm_array := 
  1686.                            ( 0 .. max_characters_in_output_line + 1 =>  1 ) ;
  1687.      
  1688.     type output_line_type is
  1689.            -- this is the data needed to correctly print out a single line of
  1690.            -- text.....
  1691.            record
  1692.              Start_Position : horizontal_measurement ;
  1693.              Stop_Position  : horizontal_measurement ;
  1694.              Justify_To     : horizontal_measurement ;
  1695.              First_Justify  : Output_Line_Index      ;
  1696.              Character_Count: Output_Line_Index      ;
  1697.              WordSpace_Count: Output_Line_Index      ;
  1698.              the_character  : charact_array          ;
  1699.              the_width      : measure_array          ;
  1700.              font_changes   : boolean                ; -- if any font changes
  1701.              Font_Number    : font_nm_array          ;
  1702.              Special_Options: boolean                ; -- true if any of the 
  1703.              double_strike  : boolean_array          ; -- following boolean 
  1704.              offset_strike  : boolean_array          ; -- arrays contain any
  1705.              underline      : boolean_array          ; -- true values...
  1706.              Sub_Or_Supers  : updownp_array          ; 
  1707.            end record ;
  1708.            -- note that each array has a position on each side of the 
  1709.            -- valid positions for blank character position.  this makes
  1710.            -- checking for changes of state easier...
  1711.             
  1712.     type output_line_pointer is access output_line_type ;
  1713.      
  1714.     blank_output_line : constant output_line_type :=
  1715.              ( 0 , 0 , 0 , 0 , 0 , 0 ,
  1716.                cleared_char ,
  1717.                cleared_meas ,
  1718.                false , cleared_font ,
  1719.                false , cleared_bool , cleared_bool , cleared_bool , 
  1720.                        cleared_updn ) ;
  1721.                 
  1722.     max_line_length : constant integer := 513 ;
  1723.                 -- however, the last position is reserved, so the user 
  1724.                 -- can only send over up to 512 characters....
  1725.      
  1726.     subtype input_line_index is integer range 0 .. max_line_length ;
  1727.      
  1728.     Type Input_Line_Type is array ( input_line_index
  1729.                          range 1 .. max_line_length ) of extended_character ;
  1730.      
  1731.     Input_Line        : Input_Line_Type  ;
  1732.     Input_Line_Length : Input_Line_Index ;
  1733.      
  1734.     waiting_output_line : output_line_pointer ;
  1735.     waiting_output_invalid_breaks : boolean_array ;
  1736.      
  1737.     rightmost_text_position     : horizontal_measurement ;
  1738.     leftmost_para_text_position : horizontal_measurement ;
  1739.     leftmost_text_position      : horizontal_measurement ;
  1740.     leftmost_normal_position    : horizontal_measurement ;
  1741.       -- used for filling off, has left margin and sub paragraph
  1742.       -- is the default place to go.
  1743.     leftmost_edge_position      : horizontal_measurement ;
  1744.       -- used for page numbers, right to left margin
  1745.      
  1746.     type Line_Modification_Type is ( Nothing , Center_mod , Right_Justify   ,
  1747.                                      To_Left_Margin ) ;
  1748.            -- to_left_margin is only used by the page number routines and
  1749.            -- the headers and footers
  1750.      
  1751.     type Line_Modification_Status is ( Off , Do_Forever , Do_While_Counting ) ;
  1752.      
  1753.     Type Permanent_And_Temporary_Character_Changes is
  1754.                 ( Subscriptc , Superscriptc , Underline , 
  1755.                   Underline_Continuous , Bold , Shadow ) ;
  1756.                    
  1757.     Type Character_Changes_Array is 
  1758.            array ( Permanent_And_Temporary_Character_Changes ) of boolean ;
  1759.      
  1760.     no_character_changes : constant character_changes_array := 
  1761.                                 ( subscriptc .. shadow => false ) ;
  1762.                                  
  1763.     type formatting_parameters is
  1764.                 record
  1765.                   Left_Indentation   : horizontal_measurement ;
  1766.                   Right_Indentation  : horizontal_measurement ; -- only fill on
  1767.                   Paragraph_Indent   : horizontal_measurement ; -- only fill on
  1768.                   Subsequent_Line_Ind: horizontal_measurement ; -- only fill on
  1769.                   Filling_On         : boolean  ;
  1770.                   Justification_On   : boolean  ;
  1771.                   Fill_Before_Special: boolean  ;
  1772.                   Just_Before_Special: boolean  ;
  1773.                   Delay_Justification_Till_After_Dots : boolean ;
  1774.                   -- Special Line Handling Information
  1775.                   Line_Modification  : Line_Modification_Type ;
  1776.                   Modification_Status: Line_Modification_Status ;
  1777.                   Modify_To_Do       : Integer                  ;
  1778.                   -- now, how to modify each character...
  1779.                   Permanent_Character_Changes : Character_Changes_Array ;
  1780.                   -- The settings set by the .bold etc. commands....
  1781.                   Temporary_Character_Changes : Character_Changes_Array ;
  1782.                   -- This holds the settings temporarily when we go into a 
  1783.                   -- header/footer/fnote.  It is filled on entry, and is 
  1784.                   -- emptied on end of the special item
  1785.                   Current_Character_Changes   : Character_Changes_Array ;
  1786.                   -- The settings set by the .bold etc. commands as modified by
  1787.                   -- the printer control character settings (which get reset at
  1788.                   -- the end of the line if filling off and at the end of the 
  1789.                   -- paragraph if filling is on... This holds the temporary 
  1790.                   -- character changes settings normally, however when we are 
  1791.                   -- in a header/footer/footnote, then this gets moved to 
  1792.                   -- temporary and gets cleared to hold the settings for the 
  1793.                   -- special item... at end of the special item, is reloaded 
  1794.                   -- from temporary
  1795.                 end record ;
  1796.                  
  1797.     current_formatting_parameters : formatting_parameters ;
  1798.     blank_formatting_parameters   : constant formatting_parameters 
  1799.                       := ( 0 , 0 , 0 , 0 , 
  1800.                            false , false , false , false , false , 
  1801.                            nothing , off , 0 , 
  1802.                            no_character_changes , 
  1803.                            no_character_changes , 
  1804.                            no_character_changes ) ;
  1805.      
  1806.     -- Now, we have some character processing information
  1807.      
  1808.     -- A_Char_Type is the list of the different values a character can have
  1809.     -- Note that it can only have ONE value at a time
  1810.     type a_char_type is ( 
  1811.                           Subscript_Start    ,
  1812.                           Subscript_Stop     ,
  1813.                           Subscript_Toggle   ,
  1814.                           Superscript_Start  ,
  1815.                           Superscript_Stop   ,
  1816.                           Superscript_Toggle ,
  1817.                           Underline_Start    ,
  1818.                           Underline_Stop     ,
  1819.                           Underline_Toggle   ,
  1820.                           UCont_Start        ,
  1821.                           UCont_Stop         ,
  1822.                           UCont_Toggle       ,
  1823.                           UFoot_Start        ,
  1824.                           UFoot_Stop         ,
  1825.                           UFoot_Toggle       ,
  1826.                           Bold_Start         ,
  1827.                           Bold_Stop          ,
  1828.                           Bold_Toggle        ,
  1829.                           Shadow_Start       ,
  1830.                           Shadow_Stop        ,
  1831.                           Shadow_Toggle      ,
  1832.                           Temp_Font_Start    ,
  1833.                           Temp_Font_Stop     ,
  1834.                           Temp_Font_Toggle   ,
  1835.                           Soft_Hyphen        ,
  1836.                           Dot_Leader         ,
  1837.                           Character_Tab      ,
  1838.                           Actual_Space       ,
  1839.                           Forced_Space       ,
  1840.                           Text_Character     ,
  1841.                           Illegal_Character  
  1842.                         ) ;
  1843.                     
  1844.     -- Char_Types is an array which provides a mapping from a character to
  1845.     -- find if it is a Text_Character or a Print Control Character
  1846.      
  1847.     type type_char_types is array ( extended_character ) of a_char_type ;
  1848.      
  1849.     char_types : type_char_types ;
  1850.      
  1851.     -- Default_Characters_Array is an array which provides a mapping from
  1852.     -- the Print Control Characters to their default values
  1853.      
  1854.     Type Type_Control_Character_Array is array ( a_char_type )
  1855.                                                     of extended_character ;
  1856.     Default_Characters_Array : Type_Control_Character_Array ;
  1857.      
  1858.     -- Current_Characters_Array contains the current settings for the
  1859.     -- printer control characters
  1860.      
  1861.     Current_Characters_Array : Type_Control_Character_Array ;
  1862.      
  1863.     character_tab_positions       : boolean_array := cleared_bool ;
  1864.      
  1865.     -- End of character processing information
  1866.      
  1867.     in_header_or_footer        : boolean ;
  1868.      
  1869.     Users_Requested_Abort : exception ;
  1870.      
  1871.     bad_user_command    : exception ; -- raised when the user has a bad
  1872.                                       -- command and we can no longer parse
  1873.                                       -- the input line.
  1874.                                        
  1875.     Function User_Pause ( Message : String ; 
  1876.                           Prompt_For_Halt : boolean := false ) return boolean ;
  1877.      
  1878.     procedure command_error ( s : in string ; show_cmd : boolean := false ;
  1879.                                               loc : in input_line_index :=0;
  1880.                                               loc2: in input_line_index :=0) ;
  1881.      
  1882.     Procedure Input_Line_To_Output_Line ;
  1883.       -- change the current input line into an acceptable output line  is
  1884.        
  1885.   end print_in_to_out ;
  1886.    
  1887.   Package body print_in_to_out is
  1888.   
  1889.     Function User_Pause ( Message : String ; 
  1890.                           Prompt_For_Halt : boolean := false ) return boolean is
  1891.       Output_Message : String ( 1 .. 28 ) := " Tap <space> to continue... " ;
  1892.       Other_Output_Message : String ( 1 .. 18 ) := " [or `H` to Halt] " ;
  1893.       Output_Length : integer ;
  1894.       ch : character ;
  1895.     begin -- User_Pause 
  1896.       If Prompt_For_Halt then
  1897.         Output_Length := Message'Length + Output_Message'Length 
  1898.                                         + Other_Output_Message'Length ;
  1899.       else
  1900.         Output_Length := Message'Length + Output_Message'Length ;
  1901.       end if ;
  1902.       goto_line_column ( master_window , window_height( master_window ) ,
  1903.                          ( highest_column_number(master_window)
  1904.                            - Output_Length ) / 2 ) ;
  1905.       put( Message & Output_Message ) ;
  1906.       if Prompt_For_Halt then
  1907.         put( Other_Output_Message ) ;
  1908.         ch := char_or_abort ( ' ' , ' ' , 'H' ) ;
  1909.       else
  1910.         ch := char_or_abort ( ' ' , ' ' ) ;
  1911.       end if;
  1912.       clear_end_of_screen (master_window , window_height(master_window) , 1 ) ;
  1913.       return ch = 'H' or ch = ascii.nul ;
  1914.       -- because ascii.nul returned on <reject> key tapped
  1915.     end User_Pause ;
  1916.      
  1917.     procedure command_error ( s : in string ; show_cmd : boolean := false ;
  1918.                                               loc : in input_line_index :=0;
  1919.                                               loc2: in input_line_index :=0) is
  1920.       -- we have a command line error at the specified position 
  1921.       temp_bool : boolean ;
  1922.       ot_string : pstring ;
  1923.     begin -- command_error
  1924.       -- must make an error message 
  1925.       clear_end_of_screen ( master_window , 19 , 1 ) ;
  1926.       goto_line_column    ( master_window , 19 , 2 ) ;
  1927.       set_reverse ( true ) ;
  1928.       put( " Command Error: " ) ;
  1929.       if show_cmd then
  1930.         put ( """"  & compress( name_tree.last_good_command ) & """ " ) ;
  1931.       end if ;
  1932.       goto_line_column    ( master_window , 20 , 2 ) ;
  1933.       put( "         " ) ;
  1934.       put( s ) ;
  1935.       set_reverse ( false ) ;
  1936.       goto_line_column    ( master_window , 21 , 2 ) ;
  1937.       for posn in 1 .. min ( 75 , input_line_length ) loop
  1938.         put( character'val ( input_line ( posn ) ) ) ;
  1939.       end loop ;
  1940.       if ( loc > 0 ) and ( loc <= 75 ) then
  1941.         goto_line_column ( master_window , 22 , loc + 1 ) ;
  1942.         set_reverse ( true ) ;
  1943.         put( '^' ) ;
  1944.         set_reverse ( false ) ;
  1945.       end if ;
  1946.       if ( loc2 > 0 ) and ( loc2 <= 75 ) then
  1947.         goto_line_column ( master_window , 22 , loc2 + 1 ) ;
  1948.         set_reverse ( true ) ;
  1949.         put( '^' ) ;
  1950.         set_reverse ( false ) ;
  1951.       end if ;
  1952.       -- wait for a space......
  1953.       temp_bool := User_Pause ( " " , true ) ;
  1954.       clear_end_of_screen ( master_window , 19 , 1 ) ;
  1955.       if temp_bool then
  1956.         -- Halt
  1957.         raise users_requested_abort ;
  1958.       else
  1959.         raise bad_user_command ;
  1960.       end if ;
  1961.     end command_error ;
  1962.  
  1963.     Procedure Input_Line_To_Output_Line is
  1964.       -- change the current input line into an acceptable output line
  1965.       -- we have an input line and would like it interpreted for lengths 
  1966.       -- and any imbedded commands and moved over to waiting_to_output
  1967.       -- area...
  1968.       last_space_posn : integer := 0 ; -- so that first spaces do not count
  1969.       word_space_ctr  : integer := 0 ; -- counts the word spaces 
  1970.       ot_posn : output_line_index := 0 ;
  1971.       cc      : extended_character     ;
  1972.       dot_leader_input_position : integer := 0 ;
  1973.       dot_leader_position : output_line_index := 0 ;
  1974.       dot_leader_leading_length : horizontal_measurement := 0 ;
  1975.       length_so_far : horizontal_measurement := 0 ;
  1976.       type type_of_request is ( Req_On , Req_Off , Req_Toggle ) ;
  1977.      
  1978.       procedure cng ( To_Change : Permanent_And_Temporary_Character_Changes ;
  1979.                       HowToDoIt : Type_Of_Request ) is
  1980.         -- this handles bold, shadow, underline, underline continuous, 
  1981.         -- and subscripts and superscripts...
  1982.         val : boolean ;
  1983.       begin -- cng
  1984.         case HowToDoIt is
  1985.           when Req_On      => val := true ;
  1986.           when Req_Off     => val := false ;
  1987.           when Req_Toggle  => val := not current_formatting_parameters
  1988.                                       .current_character_changes ( To_Change ) ;
  1989.         end case ;
  1990.         current_formatting_parameters.current_character_changes 
  1991.                                                           ( To_Change ) := val ;
  1992.         -- if they do anything with any of these commands on a line, then
  1993.         -- we will do all of the compares...and it will be slowed down 
  1994.         -- slightly
  1995.         waiting_output_line.special_options := true ;
  1996.         -- now, some items have side effects....
  1997.         -- although, these should really be treated as errors()
  1998.         if to_change = subscriptc then
  1999.           current_formatting_parameters.current_character_changes 
  2000.                                                 ( superscriptc ) := false ;
  2001.         elsif to_change = superscriptc then
  2002.           current_formatting_parameters.current_character_changes 
  2003.                                                 ( subscriptc   ) := false ;
  2004.         end if ;
  2005.       end cng ;
  2006.        
  2007.       procedure to_ot ( char_to_ot : extended_character ;
  2008.                         len_to_use : horizontal_measurement := 0 ) is
  2009.         -- if measurement is 0, then we must determine it ourselves
  2010.         actual_len_to_use : horizontal_measurement := len_to_use ;
  2011.       begin -- to_ot
  2012.         -- char_to_ot is the character to move to output stream
  2013.         if actual_len_to_use = 0 then
  2014.           -- we must determine the length to use...
  2015.           actual_len_to_use := current_font.width ( char_to_ot ) ;
  2016.         end if ;
  2017.         ot_posn := ot_posn + 1 ;
  2018.         waiting_output_line.the_character ( ot_posn ) := char_to_ot ;
  2019.         waiting_output_line.font_number( ot_posn ) := current_font.number ;
  2020.         if not waiting_output_line.special_options then 
  2021.           -- we don't need to do anything special
  2022.           waiting_output_line.the_width ( ot_posn ) := actual_len_to_use ;
  2023.         else
  2024.           -- must work special 
  2025.           -- [ Shadow ]
  2026.           if current_formatting_parameters.current_character_changes ( Shadow ) 
  2027.           then
  2028.             -- shadow affects width..
  2029.             If z_proportional = z_p_centronics then
  2030.               -- these types of printers must be handled separately
  2031.               if current_environment.printer_brand = z_cent737 then 
  2032.                 actual_len_to_use := actual_len_to_use + actual_len_to_use ;
  2033.               -- else same width applies
  2034.               end if ;
  2035.             else
  2036.               -- only do shadow on for "normal" printer (daisy)
  2037.               if char_to_ot /= extended_space 
  2038.               and then z_smart_printer = z_smart then
  2039.                 actual_len_to_use := actual_len_to_use + 1 ;
  2040.               end if ;
  2041.             end if ;
  2042.             waiting_output_line.offset_strike ( ot_posn ) := true ;
  2043.           end if ;
  2044.           waiting_output_line.the_width ( ot_posn ) := actual_len_to_use ;
  2045.           -- now, work the special options
  2046.           -- [ Subscript ]
  2047.           if current_formatting_parameters.current_character_changes 
  2048.                       ( Subscriptc ) then
  2049.             waiting_output_line.Sub_Or_Supers ( ot_posn ) := ot_subscript ;
  2050.           -- [ Superscript ]
  2051.           elsif current_formatting_parameters.current_character_changes 
  2052.                       ( Superscriptc ) then
  2053.             waiting_output_line.Sub_Or_Supers ( ot_posn ) := ot_superscript ;
  2054.           end if ;
  2055.           -- [ Underline ]
  2056.           if current_formatting_parameters.current_character_changes 
  2057.                       ( Underline ) then
  2058.             if char_to_ot /= extended_space then
  2059.               waiting_output_line.underline ( ot_posn ) := true ;
  2060.             end if ;
  2061.           -- [ Underline_Continuous ]
  2062.           elsif current_formatting_parameters.current_character_changes 
  2063.                       ( Underline_Continuous ) then
  2064.             waiting_output_line.underline ( ot_posn ) := true ;
  2065.           end if ;
  2066.           -- [ Bold ]
  2067.           if current_formatting_parameters.current_character_changes 
  2068.                       ( Bold ) then
  2069.             waiting_output_line.double_strike ( ot_posn ) := true ;
  2070.           end if ;
  2071.         end if ;
  2072.         length_so_far := length_so_far + actual_len_to_use ;
  2073.       end to_ot ;
  2074.          
  2075.       procedure do_char_tab ( posn : in integer ) is
  2076.         pn : integer ;
  2077.         length_to_add : horizontal_measurement ;
  2078.       begin -- do_char_tab
  2079.         pn := length_so_far / font_width ;
  2080.         loop
  2081.         exit when pn > output_line_index'last ;
  2082.         exit when character_tab_positions ( pn ) ;
  2083.           pn := pn + 1 ;
  2084.         end loop ;
  2085.         if pn > output_line_index'last then
  2086.           command_error ( "No tab found for this tab character." ,
  2087.                           false , posn ) ;
  2088.         else
  2089.           length_to_add := pn * font_width - length_so_far ;
  2090.           while length_to_add >= font_width loop
  2091.             to_ot ( extended_space , font_width ) ;
  2092.             length_to_add := length_to_add - font_width ;
  2093.           end loop ;
  2094.           if length_to_add > 0 then
  2095.             to_ot ( extended_space , length_to_add ) ;
  2096.           end if ;
  2097.         end if ;
  2098.       end do_char_tab ;
  2099.        
  2100.       procedure change_for_dot_leader is
  2101.         fill_amount     : integer ;
  2102.         leading_end     : integer ;
  2103.         leading_filler  : integer ;
  2104.         trailing_filler : integer ;
  2105.         trailing_start  : integer ;
  2106.         space_len       : horizontal_measurement ;
  2107.         dot_len         : horizontal_measurement ;
  2108.         each_fill_len   : horizontal_measurement ;
  2109.         dots_to_add     : integer ;
  2110.         move_amount     : integer ;
  2111.         extended_dot    : constant extended_character := extended_character (
  2112.                                                          character'pos('.') ) ; 
  2113.         old_opts        : boolean ;
  2114.       begin -- change_for_dot_leader
  2115.         -- step 1 : determine the amount to fill in
  2116.         fill_amount := rightmost_text_position 
  2117.                                 - waiting_output_line.stop_position ;
  2118.         -- note that we need enough room to start at a multiple of a space
  2119.         -- position and then put in two dots before another space...
  2120.         -- ( meaning, at least <space><dot><space><dot><space> )
  2121.         -- Various Lengths (Fixed for any font...)
  2122.         space_len := current_font.width ( extended_space ) ;
  2123.         dot_len   := current_font.width ( extended_dot   ) ;
  2124.         each_fill_len := space_len + dot_len ;
  2125.         -- step 2 : count the number of spaces and partial space to 
  2126.         --          fill in the area
  2127.         -- first, set the leading filler to make an even start...
  2128.         leading_end := leftmost_normal_position + dot_leader_leading_length ;
  2129.         leading_filler := font_width + each_fill_len
  2130.                                 - ( leading_end mod each_fill_len ) ;
  2131.         trailing_start := rightmost_text_position 
  2132.                                 - ( waiting_output_line.stop_position 
  2133.                                         - leading_end ) ;
  2134.         trailing_filler := trailing_start mod font_width + font_width ;
  2135.         fill_amount := fill_amount - leading_filler - trailing_filler ;
  2136.         if fill_amount < each_fill_len then
  2137.           -- not enough room for a dot....
  2138.           command_error("Not Enough room on line for Dot Leader.",
  2139.                                            false, dot_leader_input_position ) ;
  2140.         end if ;
  2141.         -- we get here knowing how much to do...
  2142.         -- make the fill amount even....
  2143.         trailing_filler := trailing_filler + fill_amount mod each_fill_len ;
  2144.         -- and do dots to add...
  2145.         dots_to_add := fill_amount / each_fill_len ;
  2146.         -- step 3 : move all text over by that amount ( only do special if
  2147.         --          special is set..
  2148.         -- Note that we need to add in <leading fill><2 places for each dot>
  2149.         --              <trailing fill>
  2150.         -- have to move over text ( dot_leader_position .. waiting_output_line.
  2151.         --                                                  character_count)
  2152.         move_amount := dots_to_add + dots_to_add + 2 ;
  2153.         for posn in reverse dot_leader_position .. waiting_output_line
  2154.                                                     . character_count loop
  2155.           waiting_output_line.the_character( posn + move_amount )
  2156.                                 := waiting_output_line.the_character( posn ) ;
  2157.           waiting_output_line.the_width( posn + move_amount )
  2158.                                 := waiting_output_line.the_width( posn ) ;
  2159.           waiting_output_line.font_number( posn + move_amount )
  2160.                                 := waiting_output_line.font_number( posn ) ;
  2161.           waiting_output_line.double_strike( posn + move_amount )
  2162.                                 := waiting_output_line.double_strike( posn ) ;
  2163.           waiting_output_line.offset_strike( posn + move_amount )
  2164.                                 := waiting_output_line.offset_strike( posn ) ;
  2165.           waiting_output_line.Underline( posn + move_amount )
  2166.                                 := waiting_output_line.Underline( posn ) ;
  2167.           waiting_output_line.Sub_Or_Supers( posn + move_amount )
  2168.                                 := waiting_output_line.Sub_Or_Supers( posn ) ;
  2169.         end loop ;
  2170.         waiting_output_line.character_count 
  2171.                     := waiting_output_line.character_count + move_amount ;
  2172.         -- step 4 : put in the spaces & widths
  2173.         old_opts := waiting_output_line.special_options ;
  2174.         waiting_output_line.special_options := false ;
  2175.         ot_posn := dot_leader_position - 1 ; -- cause to_ot adds one...
  2176.         to_ot( extended_space , leading_filler ) ;
  2177.         for posn in 1 .. dots_to_add loop
  2178.           to_ot( extended_dot   , dot_len   ) ;
  2179.           to_ot( extended_space , space_len ) ;
  2180.         end loop ;
  2181.         -- yes, the last part of dot leader could possibly be two spaces long..
  2182.         to_ot( extended_space , trailing_filler ) ;
  2183.         waiting_output_line.special_options := old_opts ;
  2184.         if old_opts then
  2185.           -- we must clear them out...
  2186.           for posn in dot_leader_position .. 
  2187.                       dot_leader_position + move_amount - 1 loop 
  2188.             waiting_output_line.double_strike ( posn ) := false ;
  2189.             waiting_output_line.offset_strike ( posn ) := false ;
  2190.             waiting_output_line.underline     ( posn ) := false ;
  2191.             waiting_output_line.sub_or_supers ( posn ) := normal;
  2192.           end loop ;
  2193.         end if ;
  2194.         -- step 5 : fix the line information to account for added spaces.
  2195.         waiting_output_line.stop_position  := rightmost_text_position ;
  2196.         waiting_output_line.justify_to     := waiting_output_line.stop_position;
  2197.         waiting_output_line.first_justify  := waiting_output_line
  2198.                                         .character_count + 1 ; 
  2199.       exception
  2200.         when bad_user_command => waiting_output_line.all := blank_output_line ;
  2201.                                  -- simply return a blank line....
  2202.       end change_for_dot_leader ;
  2203.        
  2204.       procedure smooth_out_line is
  2205.         -- make sure that any spaces which are too large are broken up into
  2206.         -- smaller spaces....
  2207.         space_len       : horizontal_measurement ;
  2208.         pos_to_check    : output_line_index      ;
  2209.         last_pos_to_check:output_line_index      ;
  2210.       begin -- smooth_out_line
  2211.         space_len := current_font.width ( extended_space ) ;
  2212.         pos_to_check := 1 ;
  2213.         last_pos_to_check := waiting_output_line.character_count ;
  2214.         while pos_to_check <= last_pos_to_check loop
  2215.           -- check each position for a wide space
  2216.           if waiting_output_line.the_character ( pos_to_check ) 
  2217.                                 = extended_space
  2218.           and then waiting_output_line.the_width ( pos_to_check ) 
  2219.                                 > space_len then
  2220.             -- must break this up
  2221.             -- fix master variables
  2222.             for posn in reverse pos_to_check .. 
  2223.                                   waiting_output_line.character_count loop
  2224.               -- move over each character ...
  2225.               waiting_output_line.the_character( posn + 1 )
  2226.                                 := waiting_output_line.the_character( posn ) ;
  2227.               waiting_output_line.the_width( posn + 1 )
  2228.                                 := waiting_output_line.the_width( posn ) ;
  2229.               waiting_output_line.font_number( posn + 1 )
  2230.                                 := waiting_output_line.font_number( posn ) ;
  2231.               waiting_output_line.double_strike( posn + 1 )
  2232.                                 := waiting_output_line.double_strike( posn ) ;
  2233.               waiting_output_line.offset_strike( posn + 1 )
  2234.                                 := waiting_output_line.offset_strike( posn ) ;
  2235.               waiting_output_line.Underline( posn + 1 )
  2236.                                 := waiting_output_line.Underline( posn ) ;
  2237.               waiting_output_line.Sub_Or_Supers( posn + 1 )
  2238.                                 := waiting_output_line.Sub_Or_Supers( posn ) ;
  2239.             end loop ;
  2240.             waiting_output_line.character_count 
  2241.                         := waiting_output_line.character_count + 1 ;
  2242.             -- now, split up the widths...
  2243.             waiting_output_line.the_width ( pos_to_check ) := space_len ;
  2244.             waiting_output_line.the_width ( pos_to_check + 1 ) 
  2245.                     := waiting_output_line.the_width ( pos_to_check + 1 )
  2246.                                         - space_len ;
  2247.             last_pos_to_check := waiting_output_line.character_count ;
  2248.           end if ;
  2249.           pos_to_check      := pos_to_check + 1 ;
  2250.         end loop ;
  2251.         waiting_output_line.first_justify  := waiting_output_line
  2252.                                         .character_count + 1 ; 
  2253.       end smooth_out_line ;
  2254.        
  2255.     begin -- Input_Line_to_output_line
  2256.       -- first, we need to clear the output line fancy items...
  2257.       if waiting_output_line.font_changes then
  2258.         waiting_output_line.font_changes      := false        ; 
  2259.         waiting_output_line.font_number       := cleared_font ;
  2260.       end if ;
  2261.       if waiting_output_line.special_options then
  2262.         waiting_output_line.special_options   := false        ;
  2263.         waiting_output_line.double_strike     := cleared_bool ;
  2264.         waiting_output_line.offset_strike     := cleared_bool ;
  2265.         waiting_output_line.underline         := cleared_bool ;
  2266.         waiting_output_line.sub_or_supers     := cleared_updn ;
  2267.       end if ;
  2268.       waiting_output_invalid_breaks           := cleared_bool ;
  2269.       -- now, set in case of any special changes.....
  2270.       waiting_output_line.special_options
  2271.            := current_formatting_parameters.current_character_changes
  2272.                         /= no_character_changes ;
  2273.       -- Then, start moving things over...
  2274.       for posn in 1 .. input_line_length loop
  2275.         -- first, check to see what type of character it is...
  2276.         cc := input_line ( posn ) ;
  2277.         case char_types ( cc ) is
  2278.           when subscript_start      => cng ( Subscriptc          , Req_On     );
  2279.           when subscript_stop       => cng ( Subscriptc          , Req_Off    );
  2280.           when subscript_toggle     => cng ( Subscriptc          , Req_Toggle );
  2281.           when superscript_start    => cng ( Superscriptc        , Req_On     );
  2282.           when superscript_stop     => cng ( Superscriptc        , Req_Off    );
  2283.           when superscript_toggle   => cng ( Superscriptc        , Req_Toggle );
  2284.           when underline_start      => cng ( Underline           , Req_On     );
  2285.           when underline_stop       => cng ( Underline           , Req_Off    );
  2286.           when underline_toggle     => cng ( Underline           , Req_Toggle );
  2287.           when ucont_start          => cng ( Underline_Continuous, Req_On     );
  2288.           when ucont_stop           => cng ( Underline_Continuous, Req_Off    );
  2289.           when ucont_toggle         => cng ( Underline_Continuous, Req_Toggle );
  2290.           when ufoot_start          => if in_header_or_footer then
  2291.                                        cng ( Underline           , Req_On     );
  2292.                                        end if ;
  2293.           when ufoot_stop           => if in_header_or_footer then
  2294.                                        cng ( Underline           , Req_Off    );
  2295.                                        end if ;
  2296.           when ufoot_toggle         => if in_header_or_footer then
  2297.                                        cng ( Underline           , Req_Toggle );
  2298.                                        end if ;
  2299.           when bold_start           => cng ( Bold                , Req_On     );
  2300.           when bold_stop            => cng ( Bold                , Req_Off    );
  2301.           when bold_toggle          => cng ( Bold                , Req_Toggle );
  2302.           when shadow_start         => cng ( Shadow              , Req_On     );
  2303.           when shadow_stop          => cng ( Shadow              , Req_Off    );
  2304.           when shadow_toggle        => cng ( Shadow              , Req_Toggle );
  2305.           when temp_font_start      => waiting_output_line.font_changes := true;
  2306.                                        -- even if we turn it on and then off
  2307.                                        -- we will set it as true...
  2308.                                        -- just adds a few more compares to the
  2309.                                        -- code and is cleaner than trying to
  2310.                                        -- catch the user doing strange things..
  2311.           when temp_font_stop       => null ;
  2312.           when temp_font_toggle     => waiting_output_line.font_changes := true;
  2313.           when soft_hyphen          => null ;
  2314.           when dot_leader           => if dot_leader_position /= 0 then
  2315.                                          command_error ( 
  2316.                                            "Too many Dot Leader Characters." ,
  2317.                                            false , 
  2318.                                            dot_leader_input_position , posn ) ;
  2319.                                        else
  2320.                                          dot_leader_input_position := posn ;
  2321.                                          -- above line just to make error 
  2322.                                          -- message exact
  2323.                                          dot_leader_position := ot_posn + 1 ;
  2324.                                          dot_leader_leading_length 
  2325.                                                              := length_so_far ;
  2326.                                        end if ;
  2327.           when character_tab        => -- move until we have a true
  2328.                                        -- character_tab_position or end of line
  2329.                                        do_char_tab ( posn ) ;
  2330.           when actual_space         => to_ot ( extended_space , space_width ) ;
  2331.                                        if last_space_posn + 1 /= posn then
  2332.                                          -- we have a new word space
  2333.                                          word_space_ctr := word_space_ctr + 1;
  2334.                                        end if ;
  2335.                                        last_space_posn := posn ;
  2336.           when forced_space         => to_ot ( extended_space , space_width ) ;
  2337.                                        waiting_output_invalid_breaks ( ot_posn )
  2338.                                                 := true ;
  2339.           when text_character       => to_ot ( cc ) ;
  2340.           when illegal_character    => null ;
  2341.         end case ;
  2342.       end loop ;
  2343.       -- now, must set the start & stop positions, etc.....
  2344.       waiting_output_line.start_position    := leftmost_normal_position ;
  2345.       waiting_output_line.stop_position     := 
  2346.                 waiting_output_line.start_position + length_so_far ;
  2347.       waiting_output_line.character_count   := Ot_Posn ;
  2348.       waiting_output_line.wordspace_count   := word_space_ctr ;
  2349.       if current_formatting_parameters.Justification_On then
  2350.         waiting_output_line.justify_to    := rightmost_text_position ;
  2351.         waiting_output_line.first_justify := 1 ;
  2352.       else
  2353.         waiting_output_line.justify_to    := waiting_output_line.stop_position ;
  2354.         waiting_output_line.first_justify := waiting_output_line
  2355.                                         .character_count + 1 ;
  2356.       end if ;
  2357.    -- put ( ascii.cr ) ;
  2358.    -- put ( "Start_Posn" ) ; put (waiting_output_line.start_position
  2359.                                                        -- , 5 ) ; put(ascii.cr);
  2360.    -- put ( "Stop_Posn " ) ; put (waiting_output_line.stop_position
  2361.                                                        -- , 5 ) ; put(ascii.cr);
  2362.    -- put ( "Character " ) ; put (Ot_Posn                , 5 ) ; put(ascii.cr);
  2363.    -- put ( "WordSpaces" ) ; put (word_space_ctr         , 5 ) ; put(ascii.cr);
  2364.    -- put ( "JustifyTo " ) ; put (waiting_output_line.justify_to
  2365.                                                        -- , 5 ) ; put(ascii.cr);
  2366.    -- put ( "First_Jus " ) ; put (waiting_output_line.first_justify
  2367.                                                        -- , 5 ) ; put(ascii.cr);
  2368.    -- put ( ascii.cr ) ;
  2369.       if dot_leader_position /= 0
  2370.       and then not current_formatting_parameters.Filling_on then
  2371.         -- we have to work a dot leader...justify starting with the 
  2372.         -- specified position ...
  2373.         change_for_dot_leader ;
  2374.         smooth_out_line       ;
  2375.       end if ;
  2376.     end Input_Line_to_output_line ;
  2377.      
  2378.   begin -- print_in_to_out ;
  2379.     waiting_output_line        := new output_line_type ;
  2380.   end print_in_to_out  ;
  2381.       
  2382.   --$$$- PRNTINOT
  2383.  
  2384. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2385. --prntout
  2386. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2387.  
  2388.   --$$$+ PRNTOUT
  2389.   
  2390.   --
  2391.   -- File 0xx
  2392.   --
  2393.   -- Formatter Written By Robert S. Cymbalski
  2394.   --                      Science Applications International Corporation
  2395.   --                      Ada Software Development Project Team
  2396.   --
  2397.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  2398.   --
  2399.     
  2400.   with string_library     ;
  2401.   use  string_library     ;
  2402.    
  2403.   with crt_windows        ;
  2404.   use  crt_windows        ;
  2405.    
  2406.   with printer_globals    ;
  2407.   use  printer_globals    ;
  2408.      
  2409.   with printf             ;
  2410.   use  printf             ;
  2411.    
  2412.   with print_in_to_out    ;
  2413.   use  print_in_to_out    ;
  2414.    
  2415.   Package print_out is
  2416.    
  2417.     -- All packages that use this package are device independent 
  2418.     -- (although they may be font dependent.....)
  2419.      
  2420.     -- The main goal of this package is to work with single lines and 
  2421.     -- output them to the output device...
  2422.      
  2423.     type physical_parameters is
  2424.            record
  2425.              -- Horizontal Information 
  2426.              Paper_Width        : horizontal_measurement ; 
  2427.              Left_Margin        : horizontal_measurement ; 
  2428.              Right_Margin       : horizontal_measurement ; -- only fill on
  2429.              Binding_Edge       : horizontal_measurement ;
  2430.              Printing_Left_Side: Boolean                := true ;
  2431.              real_center_right : Horizontal_measurement := 0 ;
  2432.              real_center_left  : Horizontal_measurement := 0 ;
  2433.              real_right        : Horizontal_measurement := 0 ;
  2434.              real_left         : Horizontal_measurement := 0 ;
  2435.              -- Vertical Information
  2436.              Paper_Length       : Vertical_Measurement   ;
  2437.              Top_Margin         : Vertical_Measurement   ;
  2438.              Bottom_Margin      : Vertical_Measurement   ;
  2439.            end record ;
  2440.      
  2441.     --
  2442.     -- they point as follows :
  2443.     --
  2444.     --  Real-left          Real-cntr-right   Real-cntr-left        Real-right
  2445.     --  v                                v   v                              v
  2446.     --  this is the text that is in the      And this is the text which is in
  2447.     --  first column.  You will  note that   the second column.  It wraps ar-
  2448.     --  it wraps around just on this side.   ound only on its side.
  2449.     --
  2450.     --
  2451.      
  2452.     current_physical_parameters : physical_parameters ;
  2453.      
  2454.     type place_for_page_number is ( Left_Side , Right_Side , 
  2455.                                     Center , Alternating ) ;
  2456.      
  2457.     type Heading_Or_Footing_line is private ;
  2458.      
  2459.     type Heading_Or_Footing_line_pointer is access Heading_Or_Footing_line ;
  2460.      
  2461.     type document_parameters is
  2462.            record
  2463.              -- Page Numbering Information
  2464.              Page_Numbering_On  : boolean                ;
  2465.              Current_Page_Number: integer                ;
  2466.              Section_Numbering_On:boolean                ;
  2467.              Current_Section_Num: integer                ;
  2468.              Number_Page_At_Top : boolean                ;
  2469.              Page_Number_Goes   : place_for_page_number  ;
  2470.              Page_Prefix_Suffix : pstring                ;
  2471.              Page_Heading_Footing_VMI : vertical_measurement ;
  2472.              -- Heading Information
  2473.              Heading_Lines      : integer                ;
  2474.              Heading_Height     : vertical_measurement   ;
  2475.              Heading_Pointer    : Heading_Or_Footing_line_pointer ;
  2476.              -- Footing Information
  2477.              Footing_Lines      : integer                ;
  2478.              Footing_Height     : vertical_measurement   ;
  2479.              Footing_Pointer    : Heading_Or_Footing_line_pointer ;
  2480.              -- Foot Note Information
  2481.              FootNote_Lines     : integer                ;
  2482.              FootNote_Height    : vertical_measurement   ;
  2483.              FootNote_Pointer   : Heading_Or_Footing_line_pointer ;
  2484.            end record ;
  2485.    
  2486.     current_document_parameters : document_parameters ;
  2487.      
  2488.     need_to_start_page : boolean := true ;
  2489.      
  2490.     Output_Permitted : Boolean := True ;
  2491.      
  2492.     function page_to_pstring return pstring ;
  2493.     
  2494.     Procedure Pstring_To_Output_Line ( Ps : pstring ;
  2495.                                        OtLine : in out output_line_pointer ) ;
  2496.       -- change a standard pstring into an acceptable output line
  2497.      
  2498.     procedure output_a_line ( line : in     output_line_pointer ) ;
  2499.      
  2500.     procedure Move_Down_Vertically ( Points_To_Move : Vertical_Measurement ) ;
  2501.      
  2502.     procedure Move_To_Vertical_Position ( New_Posn  : Vertical_Measurement ) ;
  2503.      
  2504.     procedure end_a_page ;
  2505.      
  2506.     procedure start_a_page ;
  2507.      
  2508.     procedure clear_a_list ( list_heading : in out 
  2509.                                             heading_or_footing_line_pointer ) ;
  2510.      
  2511.     procedure set_line_data( LineInfo : in out heading_or_footing_line_pointer ;
  2512.                              LineData : in output_line_type ) ;
  2513.      
  2514.     procedure set_next_ptr ( LineInfo : heading_or_footing_line_pointer ) ;
  2515.      
  2516.     function next_line_ptr ( LineInfo : heading_or_footing_line_pointer )
  2517.                              return heading_or_footing_line_pointer ;
  2518.      
  2519.     function return_line_data(LineInfo : in heading_or_footing_line_pointer)
  2520.                              return output_line_type ;
  2521.      
  2522.     procedure initialize_print_out_for_a_new_document        ;
  2523.    
  2524.     procedure finish_print_out_for_an_old_document           ;
  2525.      
  2526.     procedure close_print_out                                ;
  2527.      
  2528.     function ps_to_s ( p : in pstring ) return string ;
  2529.      
  2530.     procedure send_input_text_to_output_device ;
  2531.        
  2532.     procedure modify_a_line ( output_line : in out output_line_pointer ) ;
  2533.     
  2534.     Printer_Vertical_Position : Vertical_Measurement := 0 ;
  2535.       -- What vertical point position are we at ?
  2536.        
  2537.     Fatal_Output_Error : exception ;
  2538.      
  2539.     Last_Selected_Page_Printed : exception ;
  2540.      
  2541.     package FreeList_Heading is
  2542.       
  2543.       subtype list_item_value is heading_or_footing_line ;          --###--
  2544.        
  2545.       subtype List_Item       is heading_or_footing_line_pointer ;  --###--
  2546.        
  2547.       -- heading_or_footing_line_pointer appears once in text       --###--
  2548.       -- and heading_or_footing_line appears once in text           --###--
  2549.        
  2550.       no_set_value : constant List_Item := null ;
  2551.        
  2552.       procedure put_onto_free_list ( item : in out list_item ) ;
  2553.         -- this item is added to the free list
  2554.          
  2555.       function  get_from_free_list return list_item ;
  2556.         -- get an item back from the free list for usage...
  2557.          
  2558.       procedure clear_free_list ;
  2559.        
  2560.     private
  2561.        
  2562.       type private_item ;
  2563.       type private_pointer is access private_item ;
  2564.       type private_item is 
  2565.         record
  2566.           data       : List_Item ;
  2567.           prior_item ,
  2568.           next_item  : private_pointer ;
  2569.         end record ;
  2570.        
  2571.       no_item   : constant private_pointer := null ;
  2572.        
  2573.       item_list_head : Private_Pointer := no_item ;
  2574.       next_free_item : Private_Pointer := no_item ;
  2575.       item_list_tail : Private_Pointer := no_item ;
  2576.           
  2577.     end FreeList_Heading ;
  2578.     
  2579.   private 
  2580.    
  2581.     type heading_or_footing_line is
  2582.            record
  2583.              data : output_line_type ;
  2584.              next_line : heading_or_footing_line_pointer ;
  2585.            end record ;
  2586.             
  2587.     Printer_Position : Horizontal_Measurement := 0 ; 
  2588.       -- Where is printer's hammer relative to the paper.... 
  2589.       -- Used when doing bi-directional printing to minimize wear and
  2590.       -- tear on the printer....does not significantly speed up the 
  2591.       -- printing process 
  2592.        
  2593.     Console_Line  : charact_array          ;
  2594.     Console_Last  : output_line_index      ;
  2595.     Console_Length: output_line_index      ;
  2596.     Console_Line_Number : window_line_number ;
  2597.     A_Blank_Page  : boolean                ;
  2598.      
  2599.     page_number_line     : output_line_pointer ;
  2600.     page_number_position : output_line_index ;
  2601.     temporary_line       : output_line_pointer ;
  2602.      
  2603.     type when_to_add_a_line is ( at_top , at_bottom , never ) ;
  2604.      
  2605.   end print_out ;
  2606.    
  2607.   Package body print_out is
  2608.   
  2609.     Points_Moved_Since_Text_Sent_To_Output_Device : horizontal_measurement ;
  2610.       -- maintained by movement routines (increments)
  2611.       -- zeroed by output_a_line
  2612.       -- initialized by start_a_page
  2613.       -- checked within end_a_page in case we need to move before footer...
  2614.      
  2615.     procedure start_console_page ;
  2616.      
  2617.     Procedure Tab_Printer_To_Column_Number ( Target_Col : Output_Line_Index ) ;
  2618.      
  2619.   package body FreeList_Heading is 
  2620.     
  2621.     Function allocate_list_item ( with_new_List_Item : in List_Item )
  2622.                                 return Private_Pointer is
  2623.       -- allocate a new item & set its data List_Item to with_new_List_Item
  2624.       AN_ITEM : Private_Pointer ;
  2625.     begin
  2626.       -- make a new item
  2627.       AN_ITEM           := NEW private_Item   ;
  2628.       AN_ITEM.DATA      := WITH_NEW_List_Item ;
  2629.       AN_ITEM.NEXT_ITEM := null               ; 
  2630.       -- attach it to the list
  2631.       if item_list_tail = null then
  2632.         -- a new list
  2633.         an_item.prior_item := null    ;
  2634.         item_list_head     := an_item ;
  2635.         item_list_tail     := an_item ;
  2636.         next_free_item     := an_item ;
  2637.       else
  2638.         -- an old list
  2639.         AN_ITEM.PRIOR_ITEM       := ITEM_LIST_TAIL ;
  2640.         ITEM_LIST_TAIL.NEXT_ITEM := AN_ITEM        ;
  2641.         ITEM_LIST_TAIL           := AN_ITEM        ;
  2642.       end if;
  2643.       return AN_ITEM ;
  2644.     end ;
  2645.         
  2646.     Procedure DE_ALLOCATE_LIST_ITEM ( OLD_ITEM : in out Private_Pointer ) is
  2647.       -- de-allocate the old list item
  2648.     begin
  2649.       if OLD_ITEM = null then
  2650.         null ;  
  2651.       else
  2652.         if OLD_ITEM = ITEM_LIST_HEAD then
  2653.           ITEM_LIST_HEAD := ITEM_LIST_HEAD.NEXT_ITEM ;
  2654.         end if ;
  2655.         if OLD_ITEM = ITEM_LIST_TAIL then
  2656.           ITEM_LIST_TAIL := ITEM_LIST_TAIL.PRIOR_ITEM ;
  2657.         end if ;
  2658.         -- $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  2659.         -- *** release ( OLD_ITEM ) ;  ***
  2660.         -- $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  2661.         OLD_ITEM := null ;
  2662.       end if ;
  2663.     end ;
  2664.      
  2665.     procedure put_onto_free_list ( item : in out list_item ) is
  2666.       -- this item is added to the free list
  2667.       temp_ptr : private_pointer ;
  2668.     begin -- put_onto_free_list 
  2669.       if next_free_item = no_item 
  2670.         -- we must allocate new item onto one end of the list
  2671.       or else next_free_item = item_list_tail then
  2672.         -- we have a list, but none of the locations are empty...
  2673.         temp_ptr := allocate_list_item(item);
  2674.       else
  2675.         -- we can just put into the empty spot 
  2676.         next_free_item := next_free_item.next_item ;
  2677.         -- and we knew it was not the tail....
  2678.         next_free_item.data := item ;
  2679.       end if ;
  2680.       item := no_set_value ;
  2681.     end put_onto_free_list ;
  2682.         
  2683.     function  get_from_free_list return list_item is
  2684.       -- get an item back from the free list for usage...
  2685.       temp_ptr : private_pointer := next_free_item ;
  2686.       temp_list_item : heading_or_footing_line_pointer ;
  2687.     begin -- get_from_free_list 
  2688.       if temp_ptr = no_item then
  2689.         -- we must allocate new item from memory...
  2690.         temp_list_item := new heading_or_footing_line ;
  2691.         temp_list_item.next_line := null ;
  2692.         return temp_list_item ;
  2693.       else
  2694.         -- we must reclaim items from list ....
  2695.         next_free_item := next_free_item.prior_item ;
  2696.         temp_ptr.data.next_line := null ;
  2697.         return temp_ptr.data ;
  2698.       end if ;
  2699.     end get_from_free_list ;
  2700.         
  2701.     procedure clear_free_list is
  2702.       temp_ptr : private_pointer ;
  2703.     begin -- clear_free_list
  2704.       loop
  2705.         temp_ptr := item_list_head ;
  2706.       exit when temp_ptr = no_item ;
  2707.         de_allocate_list_item( temp_ptr ) ;
  2708.       end loop ;
  2709.     end clear_free_list ;
  2710.      
  2711.   begin -- FreeList_Heading
  2712.     -- FreeList  by SAIC/Clearwater Item Packages             26 Dec 84
  2713.     null ;
  2714.   end FreeList_Heading ;
  2715.      
  2716.     procedure ot ( c : extended_character ) is
  2717.       -- translate this character to the output character or string
  2718.       -- output to appropriate device/ also does ascii.cr , ascii.bs
  2719.       t_c : extended_character ;
  2720.        
  2721.       Procedure Finish_Plain_Line is
  2722.         User_Abort_Request : boolean := false ;
  2723.         Start_Place : Integer ;
  2724.       begin -- finish_plain_line
  2725.         -- we need to process it
  2726.         If c = extended_cr then
  2727.           -- a return....
  2728.           Console_Length := Max ( Console_Length , Console_Last ) ;
  2729.           Console_Last   := 0 ;
  2730.         else
  2731.           -- a line feed
  2732.           Console_Length := Max ( Console_Length , Console_Last ) ;
  2733.           Console_Last   := 0 ;
  2734.           if current_environment.where_to = to_screen then
  2735.             Console_Line_Number := Console_Line_Number + 1 ;
  2736.             if Console_Line_Number > window_height(master_window) - 2 then
  2737.               -- blankpage tells us that nothing has yet been printed
  2738.               -- on the screen.  Therefore, there is no need to stop.
  2739.               if not a_blank_page then
  2740.                 User_Abort_Request := User_Pause ( "Pause!" , true ) ;
  2741.                 if user_abort_request then
  2742.                   raise users_requested_abort ;
  2743.                 end if ;
  2744.               end if ;
  2745.               start_console_page ;
  2746.             end if ;
  2747.           end if ;
  2748.           -- else we are on the same page with no problems
  2749.           if Console_Length = 0 then
  2750.             if current_environment.where_to = to_screen then
  2751.               Goto_Line_Column( Master_Window , Console_Line_Number + 1 , 1 ) ;
  2752.             else
  2753.               end_dumb_output_line ;
  2754.             end if ;
  2755.           else
  2756.             -- we have a real line
  2757.             if current_environment.where_to = to_file then
  2758.               For posn in 1 .. Console_Length loop
  2759.                 file_out ( Console_Line ( Posn ) ) ;
  2760.               end loop ;
  2761.               end_dumb_output_line ;
  2762.             else
  2763.               a_blank_page := false ;
  2764.               -- if we get here, we are showing something
  2765.               Start_Place := Current_Physical_Parameters.Left_Margin 
  2766.                                                                  / Space_Width ;
  2767.               for posn in start_place .. 
  2768.                                min ( Highest_Column_Number ( master_window )
  2769.                                                , Console_Length ) loop
  2770.                 put( character'val( Console_Line( posn ) ) ) ;
  2771.               end loop ;
  2772.               Goto_Line_Column( Master_Window , Console_Line_Number + 1 , 1 ) ; 
  2773.               -- set at next line
  2774.             end if ; -- end of show screen
  2775.             Console_Length := 0 ;
  2776.           end if ;  -- end of real line
  2777.         end if ;    -- end of line feed
  2778.       end finish_plain_line ;
  2779.        
  2780.     begin -- ot
  2781.       if current_environment.ot_format = ot_fancy then
  2782.         -- this will use all the standard I/O for a printer
  2783.         if Current_Font.Mappings_Necessary then
  2784.           file_out ( Current_Font.Map_String ( c ) ( 1 ) ) ;
  2785.           for inside in 2 .. a_map_string'last loop
  2786.             t_c := Current_Font.Map_String ( c ) ( inside ) ;
  2787.             if t_c /= 0 then
  2788.               file_out ( t_c ) ;
  2789.             end if ;
  2790.           end loop ;
  2791.         else
  2792.           file_out(c) ; -- otherwise, just output it
  2793.         end if ;
  2794.       else  -- we are outputting in a plain format to screen or to file
  2795.         if c > extended_cr then
  2796.           -- normal character 
  2797.           if Console_Last < Output_Line_index'Last then
  2798.             Console_Last := Console_Last + 1 ;
  2799.           end if ;
  2800.           Console_Line ( Console_Last ) := c ;
  2801.         else
  2802.           finish_plain_line ;
  2803.         end if ;
  2804.       end if ;
  2805.     end ot ;
  2806.      
  2807.     procedure output_a_line ( line : in     output_line_pointer ) is
  2808.       Characters_Needed_To_Fill_Line               : Output_Line_Index ;
  2809.       Number_Of_Spaces_To_Add_To_Every_Word_Space  : Output_Line_Index ; 
  2810.       Number_Of_Word_Spaces_Getting_An_Extra_Space : Output_Line_Index ;
  2811.       Print_This_Line_Forward                      : Boolean           ;
  2812.       Characters_Available_To_Justify              : Integer           ;
  2813.         -- normally output_line_index, however, if the answer is less
  2814.         -- than 1 , then no justification has been requested
  2815.       Ok_Justify                                   : Boolean           ;
  2816.       Number_Of_Points_To_Add_To_Every_Character   : Output_Line_Index ;
  2817.       Number_Of_Characters_Getting_An_Extra_Point  : Output_Line_Index ;
  2818.       Last_Width                                   : Horizontal_Measurement ;
  2819.       Next_Width                                   : Horizontal_Measurement ;
  2820.       Add_To_Width                                 : Horizontal_Measurement ;
  2821.        
  2822.       Procedure Other_Ot ( out_place : Output_Line_Index ) is
  2823.         -- output a single character position ...
  2824.         c : extended_character ;
  2825.       begin -- Other_Ot 
  2826.         c := Line.The_Character ( out_place ) ;
  2827.         ot ( c ) ;
  2828.         If Line.Special_Options then
  2829.           -- we have to work special options, if they are available...
  2830.           if z_smart_printer = z_backspace then
  2831.             -- the printer is not smart enough to do subscript or superscript
  2832.             if Line.Double_Strike ( out_place ) 
  2833.             or Line.Offset_Strike ( out_place ) then
  2834.               ot ( extended_bs ) ;  -- backspace
  2835.               ot ( c ) ;
  2836.             end if ;
  2837.             if Line.UnderLine ( out_place ) then
  2838.               ot ( extended_bs ) ;
  2839.               ot ( extended_underline ) ;
  2840.             end if ;
  2841.           end if ;
  2842.         end if ;
  2843.       end other_ot ;
  2844.        
  2845.       Function Absol ( num : integer ) return integer is
  2846.       begin -- absol 
  2847.         if num < 0 then
  2848.           return - num ;
  2849.         else
  2850.           return   num ;
  2851.         end if ;
  2852.       end absol ;
  2853.        
  2854.       procedure output_the_line_now is
  2855.         Next_Direction : Integer ;
  2856.         Last_Direction : Integer ;
  2857.         Start_Position : Output_Line_Index ;
  2858.         Stop_Position  : Output_Line_Index ;
  2859.         Current_Pos    : Output_Line_Index ;
  2860.         Last_Pos       : Output_Line_Index ;
  2861.         
  2862.         Up_Or_Down     : up_or_down_position := normal ;
  2863.         Bold_is_On     : Boolean := false  ;
  2864.         Shadow_is_On   : Boolean := false  ;
  2865.         Underline_is_On: Boolean := false  ;
  2866.          
  2867.         procedure output_centronics_simple_line is
  2868.           Char_To_Ot     : extended_character;
  2869.           Total_Width_Ot : Horizontal_Measurement ;
  2870.         begin -- output_centronics_simple_line
  2871.           loop
  2872.             Char_To_Ot     := Line.The_Character ( Current_Pos ) ;
  2873.             Total_Width_Ot := Line.The_Width     ( Current_Pos ) ;
  2874.             ot ( Char_To_Ot ) ;
  2875.             -- Now, check for extra width
  2876.             if Total_Width_Ot /= 0 then
  2877.               -- we need to move
  2878.               execute_printer_command ( move_prop_points, total_width_ot);
  2879.             end if ;
  2880.           exit when Current_Pos = Stop_Position ;
  2881.             Last_Pos    := Current_Pos ;
  2882.             Current_Pos := Current_Pos + Next_Direction ;
  2883.           end loop ;
  2884.           ot ( extended_cr ) ;
  2885.         end output_centronics_simple_line ;
  2886.          
  2887.         procedure output_centronics_complex_line is
  2888.           Char_To_Ot     : extended_character;
  2889.           Total_Width_Ot : Horizontal_Measurement ;
  2890.         begin -- output_centronics_complex_line
  2891.           loop
  2892.             -- work Line. (Current_Pos)
  2893.             -- to compare last status, check Line. (Last_Pos)
  2894.             -- FONT
  2895.             If Line.Font_Changes 
  2896.             and then current_print_font /= Line.Font_Number ( Current_Pos ) then
  2897.               -- must change fonts ...
  2898.               execute_printer_command ( set_font_number , 
  2899.                                         Line.Font_Number ( Current_Pos ) ) ;
  2900.             end if ;
  2901.             Char_To_Ot     := Line.The_Character ( Current_Pos ) ;
  2902.             Total_Width_Ot := Line.The_Width     ( Current_Pos ) ;
  2903.             If not Line.Special_Options then
  2904.               -- we just output the character....
  2905.               ot ( Char_To_Ot ) ;
  2906.               -- Now, check for extra width
  2907.               if Total_Width_Ot /= 0 then
  2908.                 -- we need to move
  2909.                 execute_printer_command ( move_prop_points, total_width_ot);
  2910.               end if ;
  2911.             else
  2912.               -- we must check everything to see if we must do something amazing
  2913.               -- SUBSCRIPT/SUPERSCRIPT
  2914.               if up_or_down /= Line.Sub_Or_Supers ( Current_Pos ) then
  2915.                 -- first get back to normal
  2916.                 if up_or_down = superscript then
  2917.                   execute_printer_command ( set_subscript ) ;
  2918.                   up_or_down := normal ;
  2919.                 elsif Up_Or_Down = subscript then
  2920.                   execute_printer_command ( set_superscript ) ;
  2921.                   up_or_down := normal ;
  2922.                 end if ;
  2923.                 Case Line.Sub_Or_Supers ( Current_Pos ) is
  2924.                   when superscript => execute_printer_command( set_superscript);
  2925.                                       up_or_down := superscript ;
  2926.                   when normal      => null ;
  2927.                   when subscript   => execute_printer_command ( set_subscript );
  2928.                                       up_or_down := subscript ;
  2929.                 end case ;
  2930.               end if ; -- sub or superscript 
  2931.               If Bold_is_On /= Line.Double_Strike ( Current_Pos ) then
  2932.                 -- need to change bold settings...
  2933.                 Bold_is_On := not Bold_is_On ;
  2934.                 -- now, select Upright or Italic
  2935.                 if Bold_is_On then
  2936.                   execute_printer_command ( Bold_On ) ;
  2937.                 else
  2938.                   execute_printer_command ( Bold_Off ) ;
  2939.                 end if ;
  2940.               end if ;
  2941.               If shadow_is_On /= Line.Offset_Strike ( Current_Pos ) then
  2942.                 -- need to change shadow settings...
  2943.                 shadow_is_On := not shadow_is_On ;
  2944.                 if Shadow_is_On then
  2945.                   execute_printer_command ( Shadow_On ) ;
  2946.                 else
  2947.                   execute_printer_command ( Shadow_Off ) ;
  2948.                 end if ;
  2949.               end if ;
  2950.               If Underline_is_On /= Line.Underline ( Current_Pos ) then 
  2951.                 Underline_is_On := not Underline_is_On ;
  2952.                 if Underline_is_On then
  2953.                   execute_printer_command ( Underline_On ) ;
  2954.                 else
  2955.                   execute_printer_command ( Underline_Off ) ;
  2956.                 end if ;
  2957.               end if ;
  2958.               ot ( Char_To_Ot ) ;
  2959.               -- Now, check for extra width
  2960.               if Total_Width_Ot /= 0 then
  2961.                 -- we need to move
  2962.                 execute_printer_command ( move_prop_points, total_width_ot);
  2963.               end if ;
  2964.             end if ; -- not just font changes on the line
  2965.           exit when Current_Pos = Stop_Position ;
  2966.             Last_Pos    := Current_Pos ;
  2967.             Current_Pos := Current_Pos + Next_Direction ;
  2968.           end loop ;
  2969.           ot ( extended_cr ) ;
  2970.         end output_centronics_complex_line ;
  2971.          
  2972.         procedure output_Other_Simple_line is
  2973.           Char_To_Ot     : extended_character;
  2974.           Total_Width_Ot : Horizontal_Measurement ;
  2975.         begin -- output_Other_Simple_line
  2976.           -- we are working a simple line
  2977.           loop
  2978.             Char_To_Ot     := Line.The_Character ( Current_Pos ) ;
  2979.             Total_Width_Ot := Line.The_Width     ( Current_Pos ) ;
  2980.             if current_horizontal_motion_index /= Total_Width_Ot then
  2981.               execute_printer_command( set_hmi , total_width_ot );
  2982.             end if ;
  2983.             ot ( Char_To_Ot ) ;
  2984.             --###--RSC02
  2985.           exit when Current_Pos = Stop_Position ;
  2986.             Last_Pos    := Current_Pos ;
  2987.             Current_Pos := Current_Pos + Next_Direction ;
  2988.           end loop ;
  2989.           -- end of working simple line
  2990.         end output_Other_Simple_line ;
  2991.          
  2992.         procedure output_Other_complex_line is
  2993.           Char_To_Ot     : extended_character;
  2994.           Total_Width_Ot : Horizontal_Measurement ;
  2995.           Temp_Width_Ot  : Horizontal_Measurement ;
  2996.         begin -- output_Other_complex_line
  2997.           loop
  2998.             -- work Line. (Current_Pos)
  2999.             -- to compare last status, check Line. (Last_Pos)
  3000.             -- FONT
  3001.             If Line.Font_Changes 
  3002.             and then current_print_font /= Line.Font_Number ( Current_Pos ) then
  3003.               -- must change fonts ...
  3004.               execute_printer_command ( set_font_number , 
  3005.                                         Line.Font_Number ( Current_Pos ) ) ;
  3006.             end if ;
  3007.             Char_To_Ot     := Line.The_Character ( Current_Pos ) ;
  3008.             Total_Width_Ot := Line.The_Width     ( Current_Pos ) ;
  3009.             If not Line.Special_Options then
  3010.               -- we just output the character....
  3011.               if current_horizontal_motion_index /= Total_Width_Ot then
  3012.                 execute_printer_command( set_hmi , total_width_ot );
  3013.               end if ;
  3014.               ot ( Char_To_Ot ) ;
  3015.             else
  3016.               -- we must check everything to see if we must do something amazing
  3017.               -- SUBSCRIPT/SUPERSCRIPT
  3018.               if up_or_down /= Line.Sub_Or_Supers ( Current_Pos ) then
  3019.                 -- first get back to normal
  3020.                 if up_or_down = superscript then
  3021.                   execute_printer_command ( set_subscript ) ;
  3022.                   up_or_down := normal ;
  3023.                 elsif Up_Or_Down = subscript then
  3024.                   execute_printer_command ( set_superscript ) ;
  3025.                   up_or_down := normal ;
  3026.                 end if ;
  3027.                 Case Line.Sub_Or_Supers ( Current_Pos ) is
  3028.                   when superscript => execute_printer_command( set_superscript);
  3029.                                       up_or_down := superscript ;
  3030.                   when normal      => null ;
  3031.                   when subscript   => execute_printer_command ( set_subscript );
  3032.                                       up_or_down := subscript ;
  3033.                 end case ;
  3034.               end if ; -- sub or superscript 
  3035.               If Char_To_Ot = extended_space then
  3036.                 -- we must just worry about underlining the space area...
  3037.                 If Underline_is_On /= Line.Underline ( Current_Pos ) then
  3038.                   Underline_is_On := not Underline_is_On ;
  3039.                 end if ;
  3040.                 If Underline_is_On then
  3041.                   -- must both work this underline and handle checking overlap
  3042.                   if Line.UnderLine ( Current_Pos + Next_Direction )
  3043.                   and then Current_Font.Width ( extended_underline ) - 2 
  3044.                                    < total_width_ot then
  3045.                     -- if the next character in the direction we are going is 
  3046.                     -- supposed to be underlined, and if the current character
  3047.                     -- width is greater that 2 points less than the width of
  3048.                     -- the underline character, then
  3049.                     Temp_Width_Ot := Total_Width_Ot / 2 ;
  3050.                     execute_printer_command( set_hmi , temp_width_ot ) ;
  3051.                     Total_Width_Ot := Total_Width_Ot - Temp_Width_Ot ;
  3052.                     -- note that this only works up to double size char
  3053.                     ot ( extended_underline ) ;
  3054.                   end if ;
  3055.                   -- here, finally, do the underline and then move the
  3056.                   -- correct distance....
  3057.                   execute_printer_command( set_hmi , total_width_ot ) ;
  3058.                   ot ( extended_underline ) ;
  3059.                 else
  3060.                   if current_horizontal_motion_index /= Total_Width_Ot then
  3061.                     execute_printer_command( set_hmi , total_width_ot ) ; 
  3062.                   end if ;
  3063.                   ot ( extended_space ) ;
  3064.                 end if ;
  3065.               else
  3066.                 -- not working a space
  3067.                 If Bold_is_On /= Line.Double_Strike ( Current_Pos ) then
  3068.                   Bold_is_On := not Bold_is_On ;
  3069.                   if bold_is_On then
  3070.                     execute_printer_command ( set_hmi , 0 ) ;
  3071.                     ot ( Char_To_Ot ) ;
  3072.                   end if ;
  3073.                 end if ;
  3074.                 If Shadow_is_On /= Line.Offset_Strike ( Current_Pos ) then
  3075.                   Shadow_is_On := not Shadow_is_On ;
  3076.                 end if ;
  3077.                 If Underline_is_On /= Line.Underline ( Current_Pos ) then
  3078.                   Underline_is_On := not Underline_is_On ;
  3079.                 end if ;
  3080.                 -- here we still have to output char & work shadow & underline
  3081.                 If Shadow_is_On then
  3082.                   execute_printer_command ( set_hmi , 1 ) ;
  3083.                   ot ( Char_To_Ot ) ;
  3084.                   total_width_ot := total_width_ot - 1 ;
  3085.                 end if ;
  3086.                   -- still to output char and underline
  3087.                 If not Underline_is_On then
  3088.                   if current_horizontal_motion_index /= Total_Width_Ot then
  3089.                     execute_printer_command( set_hmi , total_width_ot ) ; 
  3090.                   end if ;
  3091.                   ot ( Char_To_Ot ) ;
  3092.                 else
  3093.                   -- here we need to do both the character and the underline
  3094.                   execute_printer_command( set_hmi , 0 ) ;
  3095.                   ot ( Char_To_Ot ) ;
  3096.                   if Line.UnderLine ( Current_Pos + Next_Direction )
  3097.                   and then Current_Font.Width ( extended_underline ) - 2 
  3098.                                    < total_width_ot then
  3099.                     -- if the next character in the direction we are going is 
  3100.                     -- supposed to be underlined, and if the current character
  3101.                     -- width is greater that 2 points less than the width of
  3102.                     -- the underline character, then
  3103.                     Temp_Width_Ot := Total_Width_Ot / 2 ;
  3104.                     execute_printer_command( set_hmi , temp_width_ot ) ;
  3105.                     Total_Width_Ot := Total_Width_Ot - Temp_Width_Ot ;
  3106.                     -- note that this only works up to double size char
  3107.                     ot ( extended_underline ) ;
  3108.                   end if ;
  3109.                   -- here, finally, do the underline and then move the
  3110.                   -- correct distance....
  3111.                   execute_printer_command( set_hmi , total_width_ot ) ;
  3112.                   ot ( extended_underline ) ;
  3113.                 end if ; -- underline on 
  3114.               end if ; -- not working a space 
  3115.             end if ; -- line had special options 
  3116.             --###--RSC02
  3117.           exit when Current_Pos = Stop_Position ;
  3118.             Last_Pos    := Current_Pos ;
  3119.             Current_Pos := Current_Pos + Next_Direction ;
  3120.           end loop ;
  3121.         end output_Other_complex_line ;
  3122.          
  3123.       begin -- output_the_line_now
  3124.         -- we can only get here for a smart printer...
  3125.         If print_this_line_forward then
  3126.           -- First, change direction if necessary 
  3127.           If not current_printer_direction_forward then
  3128.             execute_printer_command ( set_print_forward ) ;
  3129.           end if ;
  3130.           -- Then, Move to the starting Position ...
  3131.           execute_printer_command ( absolute_point_tab , Line.Start_Position ) ;
  3132.           -- Now, set the final print head location (to be used to determine
  3133.           -- direction for next line
  3134.           Printer_Position := Line.Stop_Position  ;
  3135.           Next_Direction := + 1 ;
  3136.           Last_Direction := - 1 ;
  3137.           Start_Position :=   1 ;
  3138.           Stop_Position  := Line.Character_Count ;
  3139.         else
  3140.           -- First, change direction if necessary 
  3141.           If current_printer_direction_forward then
  3142.             execute_printer_command ( set_print_backward ) ;
  3143.           end if ;
  3144.           -- Then, Move to the starting Position ...
  3145.           execute_printer_command ( absolute_point_tab , Line.Stop_Position ) ;
  3146.           -- Now, set the final print head location (to be used to determine
  3147.           -- direction for next line
  3148.           Printer_Position := Line.Start_Position ;
  3149.           Next_Direction := - 1 ;
  3150.           Last_Direction := + 1 ;
  3151.           Start_Position := Line.Character_Count ;
  3152.           Stop_Position  :=   1 ;
  3153.         end if ;
  3154.         -- do it to it.....
  3155.         Current_Pos := Start_Position ;
  3156.         Last_Pos    := Current_Pos + Last_Direction ;
  3157.         If z_proportional = z_p_centronics then
  3158.           -- like a centronics but not a centronics...
  3159.           -- We use bold as Italic
  3160.           -- We use shadow as Bold
  3161.           If ( not Line.Font_Changes ) 
  3162.           and then ( not Line.Special_Options ) then
  3163.             -- we are working a simple line
  3164.             output_centronics_simple_line ;
  3165.           else
  3166.             output_centronics_complex_line ;
  3167.           end if ; -- some special items in line 
  3168.         else
  3169.           -- we don't have a centronics-like printer
  3170.           If ( not Line.Font_Changes ) 
  3171.           and then ( not Line.Special_Options ) then
  3172.             output_other_simple_line ;
  3173.           else
  3174.             output_other_complex_line ;
  3175.           end if ;
  3176.         end if ;
  3177.         -- clear any funny settings????
  3178.         If Bold_is_On then
  3179.           if z_proportional = z_p_centronics then
  3180.             execute_printer_command ( Bold_Off ) ;
  3181.           end if ;
  3182.         end if ;
  3183.         If Underline_is_On then
  3184.           if z_proportional = z_p_centronics then
  3185.             execute_printer_command ( Underline_Off ) ;
  3186.           end if ;
  3187.         end if ;
  3188.         If Shadow_is_On then
  3189.           if z_proportional = z_p_centronics then
  3190.             execute_printer_command ( Shadow_Off ) ;
  3191.           end if ;
  3192.         end if ;
  3193.         If up_or_down /= normal then
  3194.           if up_or_down = superscript then
  3195.             execute_printer_command ( set_subscript ) ;
  3196.           else 
  3197.             -- Up_Or_Down = subscript 
  3198.             execute_printer_command ( set_superscript ) ;
  3199.           end if ;
  3200.         end if ;
  3201.       end output_the_line_now ;
  3202.        
  3203.     begin -- output_a_line
  3204.       if not output_permitted 
  3205.       or else line.character_count < 1 then
  3206.         return ; -- don't need to do anything...
  3207.       end if ;
  3208.       physical_output_lines := physical_output_lines + 1 ;
  3209.       if line.first_justify < 1
  3210.         -- Justify off because we were sent a first_justify of zero
  3211.       or else Line.Stop_Position >= Line.Justify_To then
  3212.         -- Justify off because line is longer than length to justify to
  3213.         -- or else off because both are exactly the same length
  3214.         Line.first_justify := line.character_count + 1 ;
  3215.         Line.Justify_to    := line.stop_position       ;
  3216.         Characters_Available_To_Justify := 0           ;
  3217.         ok_justify         := false                    ;
  3218.       else
  3219.         -- check for a different justify setting, which, if requested,
  3220.         -- is known to be valid...
  3221.         Characters_Available_To_Justify 
  3222.                   := Line.Character_Count - Line.First_Justify ;
  3223.         -- the number of characters to justify is the final place minus the
  3224.         -- start place which means that a ten character line has really 
  3225.         -- nine characters available for justification....
  3226.         ok_justify := ( Characters_Available_To_Justify > 0 ) ;
  3227.       end if ;
  3228.       if z_smart_printer /= z_smart then
  3229.         -- we have a dumb printer......
  3230.         -- Dumb Printers cannot change fonts in the middle of a line.....
  3231.         Tab_Printer_To_Column_Number 
  3232.                     ( Line.Start_Position / Current_Font.Font_Width ) ;
  3233.         if Line.First_Justify > 1 then
  3234.           for temp in 1 .. Line.First_Justify - 1 loop
  3235.             other_ot ( temp ) ;
  3236.           end loop ;
  3237.         end if ;
  3238.         if ( Line.First_Justify < Line.Character_Count ) then
  3239.           -- justify
  3240.           Characters_Needed_To_Fill_Line 
  3241.             := ( Line.Justify_To - Line.Stop_Position ) 
  3242.                         / Current_Font.Font_Width ;
  3243.           if Line.WordSpace_Count > 0 then
  3244.             Number_Of_Spaces_To_Add_To_Every_Word_Space  
  3245.                     := Characters_Needed_To_Fill_Line  /  Line.WordSpace_Count ;
  3246.             Number_Of_Word_Spaces_Getting_An_Extra_Space 
  3247.                     := Characters_Needed_To_Fill_Line mod Line.WordSpace_Count ;
  3248.           else
  3249.             Characters_Needed_To_Fill_Line := 0 ;
  3250.           end if ;
  3251.           if Number_Of_Spaces_To_Add_To_Every_Word_Space > 2 then  
  3252.             -- we don't fill more than two.....
  3253.             Characters_Needed_To_Fill_Line := 0 ;
  3254.           end if ;
  3255.           for temp in Line.First_Justify .. Line.Character_Count loop
  3256.             other_ot ( temp ) ;
  3257.             if Line.The_Character ( temp ) = extended_space
  3258.             and then Characters_Needed_To_Fill_Line > 0 then
  3259.               for looper in 1 ..Number_Of_Spaces_To_Add_To_Every_Word_Space loop
  3260.                 other_ot ( temp ) ;  -- same as other_ot ( extended_space )
  3261.                 Characters_Needed_To_Fill_Line 
  3262.                             := Characters_Needed_To_Fill_Line - 1 ;
  3263.               end loop ;
  3264.               if Number_Of_Word_Spaces_Getting_An_Extra_Space > 0 then
  3265.                 other_ot ( temp ) ;  -- same as other_ot ( extended_space )
  3266.                 Number_Of_Word_Spaces_Getting_An_Extra_Space 
  3267.                             := Number_Of_Word_Spaces_Getting_An_Extra_Space - 1;
  3268.                 Characters_Needed_To_Fill_Line 
  3269.                             := Characters_Needed_To_Fill_Line - 1 ;
  3270.               end if ;
  3271.               -- End Of Adding Spaces To Justify..
  3272.             end if;
  3273.             -- End Of Single Character Output ....
  3274.           end loop ;
  3275.           -- End Of Justification .....
  3276.         end if ;
  3277.         ot ( extended_cr ) ;
  3278.         -- End Of Dumb Printer ........
  3279.       else 
  3280.         -- We Have A Smart Printer.....
  3281.         -- Pick A Direction ...........
  3282.         Print_This_Line_Forward := Z_Forward -- Printer Only Prints Forward
  3283.                                              -- Or User Requested Only Forward
  3284.                         or else Absol( Printer_Position - Line.Start_Position )
  3285.                              <= Absol( Printer_Position - Line.Justify_To     );
  3286.         if ok_justify then
  3287.           Number_Of_Points_To_Add_To_Every_Character 
  3288.                       := ( Line.Justify_To - Line.Stop_Position ) 
  3289.                             / Characters_Available_To_Justify ;
  3290.           Number_Of_Characters_Getting_An_Extra_Point 
  3291.                       := ( Line.Justify_To - Line.Stop_Position ) 
  3292.                             mod Characters_Available_To_Justify ;
  3293.           if Number_Of_Points_To_Add_To_Every_Character 
  3294.               > Permanent_Font.Horizontal_Points_Per_Inch / 15 then 
  3295.             -- only justify if up to five + 1 leftover points per char
  3296.             Number_Of_Points_To_Add_To_Every_Character  := 0 ;
  3297.             Number_Of_Characters_Getting_An_Extra_Point := 0 ;
  3298.             Print_This_Line_Forward := true ;
  3299.           else
  3300.             Line.Stop_Position := Line.Justify_To ;
  3301.           end if ;
  3302.         end if ;
  3303.         -- Massage the width information to turn it into the 
  3304.         -- amount of distance to be moved between each character, not
  3305.         -- the width of each character...
  3306.         -- Now, work special centronics type printer
  3307.         If Z_Proportional = Z_P_Centronics then
  3308.           -- no need to work on the widths, it is already figured out...
  3309.           for posn in 1 .. Line.Character_Count loop
  3310.             Line.The_Width ( posn ) := 0 ;
  3311.             -- because the width holds only justification informaiton....
  3312.           end loop ;
  3313.         else
  3314.           -- must work widths
  3315.           --
  3316.           -- Currently a line such as "THIS LINE" would have the following info
  3317.           --
  3318.           -- Start At Position 104
  3319.           -- Stop  At Position 174 ( old value before ^ justify lines )
  3320.           -- Justify To        200
  3321.           --      T     H     I     S          L     I     N     E
  3322.           --     10     8     6     8     8    8     6     8     8
  3323.           --
  3324.           If print_this_line_forward then
  3325.             -- in the above line, to start at 104, we must move to 109
  3326.             -- ( 104 + 10/2 )
  3327.             Last_Width := Line.The_Width(1);
  3328.             Line.Start_Position := Line.Start_Position + Last_Width / 2 ;
  3329.             Last_Width := Last_Width - ( Last_Width / 2 ) ;
  3330.             -- note that that might not be equal to last_width / 2 !!!!
  3331.             for posn in 1 .. Line.Character_Count - 1 loop
  3332.               Next_Width := Line.The_Width ( posn + 1 ) ;
  3333.               Line.The_Width ( posn ) := Last_Width + Next_Width / 2 ;
  3334.               Last_Width := Next_Width - Next_Width / 2 ;
  3335.             end loop ;
  3336.             -- we don't care about the movement after the last character...
  3337.           else
  3338.             -- printing backwards.....
  3339.             -- in the above line, to start at 200, we must move to 
  3340.             -- 196 ( 200 - 8/2 )
  3341.             Last_Width := Line.The_Width ( Line.Character_Count ) ;
  3342.             Line.Stop_Position := Line.Stop_Position - Last_Width / 2 ;
  3343.             Last_Width := Last_Width - ( Last_Width / 2 ) ;
  3344.             -- note that that might not be equal to last_width / 2 !!!!
  3345.             for posn in reverse 2 .. Line.Character_Count loop
  3346.               Next_Width := Line.The_Width ( posn - 1 ) ;
  3347.               Line.The_Width ( posn ) := Last_Width + Next_Width / 2 ;
  3348.               Last_Width := Next_Width - Next_Width / 2 ;
  3349.             end loop ;
  3350.           end if ;
  3351.         end if ;
  3352.         if ok_justify then
  3353.           -- Now, we need to move the justification information in...
  3354.           -- Note that there are THREE ways to work proportional printing,
  3355.           -- and therefore THREE ways to figure movement...
  3356.           -- Qume: Print Character and then move a bit
  3357.           -- Diablo: Set moving Amount and then Print Character
  3358.           -- Centronics: Print Character while moving, and then move a bit
  3359.           -- for justification purposes, we need to set the width information
  3360.           -- to just the justification if we are doing the centronics stuff.
  3361.           -- but, luckily
  3362.           If print_this_line_forward then
  3363.             for posn in Line.First_Justify .. Line.Character_Count - 1 loop
  3364.               add_to_width := number_of_points_to_add_to_every_character ;
  3365.               if number_of_characters_getting_an_extra_point > 0 then
  3366.                 add_to_width := add_to_width + 1 ;
  3367.                 number_of_characters_getting_an_extra_point 
  3368.                     := number_of_characters_getting_an_extra_point -1 ;
  3369.               end if ;
  3370.               Line.The_Width ( posn ) := Line.The_Width ( posn ) + add_to_width;
  3371.             end loop ;
  3372.           else
  3373.             for posn in reverse Line.First_Justify + 1 
  3374.                                         .. Line.Character_Count loop
  3375.               add_to_width := number_of_points_to_add_to_every_character ;
  3376.               if number_of_characters_getting_an_extra_point > 0 then
  3377.                 add_to_width := add_to_width + 1 ;
  3378.                 number_of_characters_getting_an_extra_point 
  3379.                     := number_of_characters_getting_an_extra_point -1 ;
  3380.               end if ;
  3381.               Line.The_Width ( posn ) := Line.The_Width ( posn ) + add_to_width;
  3382.             end loop ;
  3383.           end if ;
  3384.         end if ;
  3385.         -- we end up here with all of the widths adjusted to correctly
  3386.         -- justify the line...so we no longer have to care about the 
  3387.         -- setting of the justify switch
  3388.         output_the_line_now ;
  3389.       end if ;
  3390.       Points_Moved_Since_Text_Sent_To_Output_Device  := 0  ;
  3391.     end output_a_line ;
  3392.      
  3393.     Procedure Tab_Printer_To_Column_Number ( Target_Col : Output_Line_Index ) is
  3394.       old_hmi : horizontal_measurement ;
  3395.       Col     : Output_Line_Index := Target_Col ;
  3396.     begin
  3397.       -- take binding into account
  3398.       If Current_Physical_Parameters.Binding_Edge /= 0 
  3399.       and then odd ( current_document_parameters.Current_Page_Number ) then
  3400.         Col := Col 
  3401.           + Current_Physical_Parameters.Binding_Edge / Current_Font.Font_Width ;
  3402.       end if ;
  3403.       if z_smart_printer /= z_smart then
  3404.         ot ( extended_cr ) ;
  3405.         for looper in 1 .. Col loop
  3406.           ot ( extended_space ) ;
  3407.         end loop ;
  3408.       elsif z_proportional = z_p_centronics then
  3409.         if current_environment.printer_brand = z_cent737 then
  3410.           ot ( extended_cr ) ;
  3411.           execute_printer_command ( move_prop_points , 15 * Col ) ;
  3412.         else 
  3413.           execute_printer_command ( Absolute_Point_Tab ,
  3414.                                     Col * current_horizontal_motion_index ) ;
  3415.         end if ;
  3416.       else
  3417.         -- for the other two types of printers
  3418.         old_hmi := current_horizontal_motion_index ;
  3419.         execute_printer_command ( set_hmi , Current_Font.Font_Width ) ;
  3420.         execute_printer_command ( abs_hor_tab , Col ) ;
  3421.         execute_printer_command ( set_hmi , Old_Hmi ) ;
  3422.       end if ;
  3423.     end Tab_Printer_To_Column_Number ;
  3424.      
  3425.     procedure start_console_page is
  3426.     begin -- start_console_page
  3427.       clear_window ( Master_Window ) ;
  3428.       Console_Last   := 0 ;
  3429.       Console_Length := 0 ;
  3430.       Console_Line_Number := 0 ;
  3431.       A_Blank_Page   := true ;
  3432.       Goto_Line_Column( Master_Window , 1 , 1 ) ;
  3433.     end start_console_page ;
  3434.      
  3435.     procedure clear_a_list ( list_heading : in out 
  3436.                                             heading_or_footing_line_pointer ) is
  3437.       line_we_are_working : heading_or_footing_line_pointer ;
  3438.       line_to_do_next     : heading_or_footing_line_pointer ;
  3439.     begin -- clear_a_list
  3440.       line_we_are_working := list_heading ;
  3441.       while line_we_are_working /= null loop
  3442.         line_to_do_next     := line_we_are_working.next_line ;
  3443.         freelist_heading.put_onto_free_list ( line_we_are_working ) ;
  3444.         -- this item is added to the free list
  3445.         line_we_are_working := line_to_do_next ;
  3446.       end loop ;
  3447.       list_heading := null ; -- to clear to nothing...
  3448.     end clear_a_list ;
  3449.      
  3450.     procedure examine_vmi is
  3451.       -- this takes care of a vmi which is greater than a limited printer
  3452.       -- can handle.  Note that this does not try to take care of reverse
  3453.       -- movement which has a large vmi
  3454.       moved_per_line : constant integer := 
  3455.                          current_font.vertical_points_per_inch / 6 ;
  3456.       still_to_move : integer ;
  3457.       old_vmi : vertical_measurement ;
  3458.     begin -- examine_vmi
  3459.       -- can only get here when really outputting and doing at least 
  3460.       -- double spacing...
  3461.       if (z_smart_printer /= z_smart) or 
  3462.           current_environment.printer_brand = z_cent737 then
  3463.         -- we need to work on it
  3464.         still_to_move := current_vertical_motion_index - moved_per_line;
  3465.         while still_to_move > 0 loop
  3466.           ot ( extended_lf ) ;
  3467.           still_to_move := still_to_move - moved_per_line ;
  3468.         end loop ;
  3469.       --###--RSC02
  3470.       end if;
  3471.     end examine_vmi ;
  3472.      
  3473.     procedure Move_Down_A_Line ( Lines_To_Move : Integer := 1 ) is
  3474.       examine_vmi_for_special_work : boolean := current_vertical_motion_index 
  3475.                                               >= printer_vertical_per_inch / 3 ;
  3476.     begin -- move_down_a_line
  3477.       if output_permitted then
  3478.         for linen in 1 .. lines_to_move loop
  3479.           ot ( extended_lf ) ;
  3480.           Printer_Vertical_Position := Printer_vertical_Position
  3481.                                           + Current_Vertical_Motion_Index ;
  3482.           if examine_vmi_for_special_work then
  3483.             examine_vmi ;
  3484.           end if ;
  3485.         end loop ;
  3486.       else
  3487.         printer_vertical_position := printer_vertical_position
  3488.                         + lines_to_move * current_vertical_motion_index ;
  3489.       end if ;
  3490.       Points_Moved_Since_Text_Sent_To_Output_Device  := 
  3491.           Points_Moved_Since_Text_Sent_To_Output_Device
  3492.           + lines_to_move * current_vertical_motion_index ;
  3493.     end move_down_a_line ;
  3494.  
  3495.     procedure Move_Down_Vertically ( Points_To_Move : Vertical_Measurement ) is
  3496.       next_position : integer ; -- integer because can take on invalid values
  3497.       temp_vmi      : vertical_measurement ;
  3498.       new_posn      : vertical_measurement ;
  3499.       examine_vmi_for_special_work : boolean := current_vertical_motion_index 
  3500.                                               >= printer_vertical_per_inch / 3 ;
  3501.     begin -- move_down_vertically
  3502.       -- if points_to_move < 1 then 
  3503.         -- return ;
  3504.       -- end if ;
  3505.       New_Posn := Printer_Vertical_Position + Points_To_Move ;
  3506.       if output_permitted then
  3507.         loop 
  3508.           next_position := Printer_Vertical_Position 
  3509.                            + Current_Vertical_Motion_Index ;
  3510.         exit when next_position > New_Posn ;
  3511.           ot ( extended_lf ) ;
  3512.           Printer_Vertical_Position := next_position ;
  3513.           if examine_vmi_for_special_work then
  3514.             examine_vmi ;
  3515.           end if ;
  3516.         end loop ;
  3517.         if printer_vertical_position /= new_posn then
  3518.           -- we must move forward slightly less than a line...
  3519.           temp_vmi := current_vertical_motion_index ;
  3520.           execute_printer_command ( set_vmi , 
  3521.                                     new_posn - printer_vertical_position ) ;
  3522.           ot ( extended_lf ) ;
  3523.           execute_printer_command ( set_vmi , temp_vmi ) ;
  3524.           Printer_Vertical_Position := New_Posn ;
  3525.         end if ;
  3526.       else
  3527.         Printer_Vertical_Position := New_Posn ;
  3528.       end if ;
  3529.       Points_Moved_Since_Text_Sent_To_Output_Device  := 
  3530.           Points_Moved_Since_Text_Sent_To_Output_Device
  3531.           + points_to_move  ;
  3532.     end move_down_vertically ;
  3533.  
  3534.     procedure Move_To_Vertical_Position ( New_Posn  : Vertical_Measurement ) is
  3535.       next_position : integer ; -- integer because can take on invalid values
  3536.       temp_vmi      : vertical_measurement ;
  3537.       to_move       : integer ;
  3538.       examine_vmi_for_special_work : boolean := current_vertical_motion_index 
  3539.                                               >= printer_vertical_per_inch / 3 ;
  3540.     begin -- move_to_vertical_position
  3541.       -- put("//PVP=> ") ; put( printer_vertical_position , 5 ) ;
  3542.       -- put("//NP => ") ; put( new_posn , 5 ) ;
  3543.       if output_permitted then
  3544.         if Printer_Vertical_Position < New_Posn then
  3545.           -- we can move there 
  3546.           Points_Moved_Since_Text_Sent_To_Output_Device  := 
  3547.               Points_Moved_Since_Text_Sent_To_Output_Device
  3548.               + new_posn - printer_vertical_position ;
  3549.           loop 
  3550.             next_position := Printer_Vertical_Position 
  3551.                              + Current_Vertical_Motion_Index ;
  3552.           exit when next_position > New_Posn ;
  3553.             ot ( extended_lf ) ;
  3554.             Printer_Vertical_Position := next_position ;
  3555.             if examine_vmi_for_special_work then
  3556.               examine_vmi ;
  3557.             end if ;
  3558.           end loop ;
  3559.         elsif Printer_Vertical_Position > New_Posn then
  3560.           -- we can move backwards...
  3561.           to_move := Printer_vertical_position - new_posn 
  3562.                      + current_vertical_motion_index - 1 ; 
  3563.           -- that forces it to hit exact or overshoot less than a line.
  3564.           execute_printer_command ( go_up_on_page , 
  3565.                                     to_move / current_vertical_motion_index ) ;
  3566.           printer_vertical_position := printer_vertical_position - to_move ;
  3567.           Points_Moved_Since_Text_Sent_To_Output_Device  := 
  3568.               Points_Moved_Since_Text_Sent_To_Output_Device
  3569.               + to_move         ;
  3570.         -- else we are there already...
  3571.         end if ;
  3572.         if printer_vertical_position /= new_posn then
  3573.           -- we must move forward slightly less than a line...
  3574.           temp_vmi := current_vertical_motion_index ;
  3575.           execute_printer_command ( set_vmi , 
  3576.                                     new_posn - printer_vertical_position ) ;
  3577.           ot ( extended_lf ) ;
  3578.           execute_printer_command ( set_vmi , temp_vmi ) ;
  3579.           Printer_Vertical_Position := New_Posn ;
  3580.         end if ;
  3581.       else
  3582.         Printer_Vertical_Position := New_Posn ;
  3583.       end if ;
  3584.     end move_to_vertical_position ;
  3585.      
  3586.     procedure set_line_information is
  3587.       -- used to be resetmax
  3588.     begin -- set_line_information
  3589.       -- this is really only needed in case we have double columns and then
  3590.       -- a page call means that the left and right margins must change....
  3591.       null ;
  3592.     end set_line_information ;
  3593.      
  3594.     procedure output_line_set( Starting_Line : Heading_Or_Footing_Line_Pointer ;
  3595.                                Number_Of_Lines : integer ;
  3596.                                Merge_Another_Line : Boolean ;
  3597.                                Merged_Line   : output_line_pointer ;
  3598.                                Merge_As_First_Line : boolean ;
  3599.                                Add_A_Blank : when_to_add_a_line := never ) is
  3600.       old_vmi : vertical_measurement := current_vertical_motion_index ;
  3601.       next_ot_line : heading_or_footing_line_pointer ;
  3602.     begin -- output_line_set 
  3603.       if old_vmi /= Current_Document_Parameters.Page_Heading_Footing_VMI then
  3604.         execute_printer_command ( set_vmi , Current_Document_Parameters
  3605.                                             .Page_Heading_Footing_VMI ) ;
  3606.       end if ;
  3607.       if add_a_blank = at_top then
  3608.         move_down_a_line ( 2 ) ;
  3609.       end if ;
  3610.       next_ot_line := Starting_line ;
  3611.       for this_line_number in 1 .. Number_Of_Lines loop 
  3612.         Temporary_Line.all := next_ot_line.data ;
  3613.         if merge_another_line then
  3614.           if this_line_number = 1 
  3615.           and then merge_as_first_line then
  3616.             -- merge it in
  3617.             output_a_line ( merged_line    ) ;
  3618.           elsif this_line_number = number_of_lines 
  3619.           and then not merge_as_first_line then
  3620.             -- merge it in at the end
  3621.             output_a_line ( merged_line    ) ;
  3622.           end if ;
  3623.         end if ;
  3624.         -- ready to print Temporary_Line 
  3625.         output_a_line ( Temporary_Line ) ;
  3626.         move_down_a_line ;
  3627.         next_ot_line := next_ot_line.next_line ;
  3628.       end loop ;
  3629.       if add_a_blank = at_bottom then
  3630.         move_down_a_line ( 1 ) ;
  3631.       end if ;
  3632.       if old_vmi /= current_vertical_motion_index then
  3633.         execute_printer_command ( set_vmi , old_vmi ) ;
  3634.       end if ;
  3635.     end output_line_set ;
  3636.      
  3637.     function page_to_pstring return pstring is
  3638.       pg_num : integer ;
  3639.       nums   : pstring ;
  3640.       pref_sufx : pstring ;
  3641.       place_for_number : integer ;
  3642.     begin -- page_to_pstring
  3643.       if current_document_parameters.section_numbering_on then
  3644.         pg_num := current_document_parameters.current_section_num ;
  3645.       else
  3646.         pg_num := current_document_parameters.current_page_number ;
  3647.       end if ;
  3648.       pref_sufx := current_document_parameters.Page_Prefix_Suffix ;
  3649.       nums := int_to_str ( pg_num ) ;
  3650.       if length ( pref_sufx ) = 0 then
  3651.         -- simplest case
  3652.         return nums ;
  3653.       else
  3654.         -- we must break it apart
  3655.         place_for_number := position ( '$' , pref_sufx ) ;
  3656.         -- we know it is non-zero because the command that sets it checks
  3657.         -- for that
  3658.         if place_for_number > 1 then
  3659.           nums := pref_sufx.data( 1 .. place_for_number - 1 ) & nums ;
  3660.         end if ;
  3661.         if place_for_number < length( pref_sufx ) then
  3662.           return nums & pref_sufx.data( place_for_number + 1 .. 
  3663.                                           length ( pref_sufx ) ) ;
  3664.         else
  3665.           return nums ;
  3666.         end if ;
  3667.       end if ;
  3668.     end page_to_pstring ;
  3669.      
  3670.     procedure generate_page_number_line is
  3671.       page_pstring : pstring := page_to_pstring ;
  3672.       temp_pstring : pstring ;
  3673.       temporary_saved_formatting_parameters : formatting_parameters ;
  3674.       new_mod : line_modification_type := to_left_margin ; -- how to modify line
  3675.     begin -- generate_page_number_line
  3676.       -- first, change the pstring page number line over to pstring...
  3677.       if length ( current_document_parameters.Page_Prefix_Suffix ) /= 0 then
  3678.         -- we would like to inform the user about the page number
  3679.         temp_pstring := " " & page_pstring ;
  3680.         while length( temp_pstring ) < 20 loop
  3681.           temp_pstring := temp_pstring & " " ;
  3682.         end loop ;
  3683.         if length ( temp_pstring ) > 20 then
  3684.           set_length ( temp_pstring , 20 ) ;
  3685.         end if ;
  3686.         otsxy( 55 , 12 , ps_to_s ( temp_pstring ) ) ;
  3687.         -- page_pstring := temp_pstring ;
  3688.       end if ;
  3689.       -- now, find out how to modify the page number line...
  3690.       if current_document_parameters.page_number_goes = center then
  3691.         new_mod := center_mod ;
  3692.       elsif current_document_parameters.page_number_goes = right_side
  3693.       or else ( current_document_parameters.page_number_goes = Alternating 
  3694.           and then odd( current_document_parameters.Current_Page_Number ) ) then
  3695.         -- here we need to move the page number to the right side of the page
  3696.         new_mod := right_justify ;
  3697.       -- else it stays on the left edge
  3698.       end if ;
  3699.       -- now, change into normal output line
  3700.       -- set to no special formatting to take place...
  3701.       temporary_saved_formatting_parameters := current_formatting_parameters ;
  3702.       current_formatting_parameters         := blank_formatting_parameters   ;
  3703.       in_header_or_footer := true ;
  3704.       -- the above turns on flag to allow ufoot character
  3705.       if new_mod /= nothing then
  3706.         current_formatting_parameters.line_modification   := new_mod    ;
  3707.         current_formatting_parameters.Modification_Status := Do_Forever ;
  3708.       end if ;
  3709.       Pstring_To_Output_Line ( page_pstring , page_number_line ) ;
  3710.       if new_mod /= nothing then
  3711.         modify_a_line ( page_number_line ) ;
  3712.       end if ;
  3713.       -- reset special formatting to the correct setting...
  3714.       current_formatting_parameters := temporary_saved_formatting_parameters ;
  3715.       in_header_or_footer := false ;
  3716.       -- if current_document_parameters.page_number_goes = center then
  3717.         -- we must find the center of the page.  Note that if we have a 
  3718.         -- binding edge we want to adjust this page number so that it 
  3719.         -- exactly lines up with the number on the other side of the 
  3720.         -- page, so we adjust the centering slightly
  3721.         -- if Current_Physical_Parameters.Binding_Edge > 0 then
  3722.           -- -- we have a binding edge to work on
  3723.           -- if odd( current_document_parameters.Current_Page_Number ) then
  3724.             -- page_start_position := page_start_position 
  3725.                              -- + ( Current_Physical_Parameters.Binding_Edge 
  3726.                                -- * Current_Font.Font_Width ) / 2 ;
  3727.           -- else
  3728.             -- -- even page
  3729.             -- page_start_position := page_start_position 
  3730.                              -- - ( Current_Physical_Parameters.Binding_Edge
  3731.                                -- * Current_Font.Font_Width ) / 2 ;
  3732.           -- end if ;
  3733.         -- -- else no adjustment needed because no binding edge
  3734.         -- end if ;
  3735.       -- end if ;
  3736.     end generate_page_number_line ;
  3737.      
  3738.     function ps_to_s ( p : in pstring ) return string is
  3739.     begin -- ps_to_s
  3740.       return p.data( 1 .. length(p) ) ;
  3741.     end ps_to_s ;
  3742.        
  3743.     procedure start_a_page is
  3744.       page_number_line_ready : boolean ;
  3745.     begin -- start_a_page
  3746.       set_reverse(true );
  3747.       otnxy( 39 , 12 , Physical_Page_Number  , 10               ) ;
  3748.       put ( " " ) ;
  3749.       set_reverse(false);
  3750.       Output_Permitted := ( Current_Document_Parameters.Current_Page_Number
  3751.                             >= Current_Environment.First_Page_To_Print )
  3752.                       and ( Current_Document_Parameters.Current_Page_Number
  3753.                             <= Current_Environment.Last_Page_To_Print  ) ;
  3754.       if current_physical_parameters.real_center_right /= 0 then
  3755.         if current_physical_parameters.Printing_Left_Side then
  3756.           current_Physical_Parameters.left_margin  
  3757.                               := current_physical_parameters.real_left ;
  3758.           current_Physical_Parameters.right_margin 
  3759.                               := current_physical_parameters.real_center_right ;
  3760.         else
  3761.           current_Physical_Parameters.left_margin 
  3762.                               := current_physical_parameters.real_center_left ;
  3763.           current_Physical_Parameters.right_margin 
  3764.                               := current_physical_parameters.real_right ;
  3765.         end if ;
  3766.         set_line_information ;
  3767.       end if ;
  3768.       if current_physical_parameters.Printing_Left_Side 
  3769.       or ( current_physical_parameters.real_center_right = 0) then
  3770.         if Output_Permitted then
  3771.           -- we need to feed in the appropriate page in the printer
  3772.           if Current_Document_Parameters.Current_Page_Number = 1 then
  3773.             execute_printer_command(start_first_page) ;
  3774.           elsif Current_Document_Parameters.Current_Page_Number = 0 then
  3775.             execute_printer_command(start_envelope) ;
  3776.           elsif (Current_Document_Parameters.Current_Page_Number 
  3777.                                  = current_environment.first_page_to_print) then
  3778.             -- a first page, but not page 1 
  3779.             execute_printer_command(start_middle_page) ;
  3780.           else
  3781.             -- eject the previous page unless we are already ready for new page
  3782.             if we_have_some_tray_loader -- then need to start page no matter 
  3783.             or else ( Printer_Vertical_Position < 
  3784.                          Current_Physical_Parameters.Paper_Length ) then
  3785.               -- or not at end of a page anyway...
  3786.               execute_printer_command(end_page_start_another) ;
  3787.             end if ;
  3788.           end if ;
  3789.           if ( not current_environment.continuous_forms )  and
  3790.              ( current_environment.where_to = to_printer ) then
  3791.             if User_Pause ( "Insert the Next Page. " , true ) then 
  3792.               raise Users_Requested_Abort ;
  3793.             end if ;
  3794.           end if ;
  3795.         end if ;
  3796.       end if ;
  3797.       Printer_Vertical_Position := 0 ;
  3798.       -- that says where the Top of the current character will print...
  3799.       -- we need to do the top margin stuff....
  3800.       -- because we are either starting a new page 
  3801.       move_to_vertical_position ( current_Physical_Parameters.top_margin ) ;
  3802.       -- we are now sitting on the first line on the page ...
  3803.       if ( current_physical_parameters.Printing_Left_Side 
  3804.       or ( current_physical_parameters.real_center_right = 0) )
  3805.       and then Output_Permitted then 
  3806.         -- first column or not double column and we are printing
  3807.         -- this is either first col of two, or single column
  3808.         -- we are outputting now 
  3809.         -- page number ?
  3810.         if Current_Document_Parameters.Page_Numbering_On 
  3811.         and Current_Document_Parameters.Number_Page_At_Top then
  3812.           generate_page_number_line ;
  3813.           page_number_line_ready := true ;
  3814.         else
  3815.           page_number_line_ready := false ;
  3816.         end if ;
  3817.         if Current_Document_Parameters.Heading_Lines > 0 then
  3818.           output_line_set ( Current_Document_Parameters.Heading_Pointer ,
  3819.                             Current_Document_Parameters.Heading_Lines   ,
  3820.                             page_number_line_ready ,
  3821.                             page_number_line ,
  3822.                             true ,
  3823.                             at_bottom ) ;
  3824.         elsif page_number_line_ready then
  3825.           output_a_line ( page_number_line ) ;
  3826.           move_down_a_line ( 2 ) ;
  3827.         end if ;
  3828.         -- end   we are outputting
  3829.       else
  3830.         -- second column or else are not printing
  3831.         -- we need to put in the <cr><lf>
  3832.         -- if Output_Permitted is false, 
  3833.         -- then do_do_crlf just advances Printer_Vertical_Position by vmi * x
  3834.         if Current_Document_Parameters.Heading_Lines > 0 then
  3835.           move_down_a_line ( Current_Document_Parameters.Heading_Lines + 1 ) ;
  3836.         elsif Current_Document_Parameters.Page_Numbering_On 
  3837.           and Current_Document_Parameters.Number_Page_At_Top then
  3838.           move_down_a_line ( 2 ) ;
  3839.         end if ;
  3840.       end if ;
  3841.       Need_To_Start_Page := false ;
  3842.     end start_a_page ;
  3843.      
  3844.     procedure end_a_page is
  3845.       FootNote_And_Footer_Loc : vertical_measurement ;
  3846.       Footer_Loc              : vertical_measurement ;
  3847.       PageNum_Loc             : vertical_measurement ;
  3848.       bottom_Loc              : vertical_measurement ;
  3849.       page_number_line_ready  : boolean              ;
  3850.       moving_vmi              : vertical_measurement ;
  3851.       old_vmi                 : vertical_measurement ;
  3852.       lines_we_can_output     : integer              ;
  3853.        
  3854.       procedure generate_one_inch_line( ot_line : in out output_line_pointer) is
  3855.         und_width : horizontal_measurement ;
  3856.         num       : integer                ;
  3857.         ot_pos    : horizontal_measurement ;
  3858.       begin -- generate_one_inch_line
  3859.         ot_line.all            := blank_output_line     ;
  3860.         und_width := current_font.width ( extended_underline ) ;
  3861.         num       := current_font.horizontal_points_per_inch / und_width ;
  3862.         Ot_Pos    := leftmost_edge_position;
  3863.         ot_line.Start_Position := Ot_Pos                ;
  3864.         for posn in 1 .. num loop
  3865.           ot_line.the_character ( posn ) := extended_underline ;
  3866.           ot_line.the_width     ( posn ) := und_width          ;
  3867.           ot_line.Font_Number   ( posn ) := current_font.number;
  3868.           Ot_Pos := Ot_Pos + und_width ;
  3869.         end loop ;
  3870.         ot_line.Stop_Position  := Ot_Pos                ;
  3871.         ot_line.Justify_To     := Ot_Pos                ;
  3872.         ot_line.First_Justify  := 0                     ;
  3873.         ot_line.Character_Count:= num                   ;
  3874.         ot_line.WordSpace_Count:= 0                     ;
  3875.       end generate_one_inch_line ;
  3876.        
  3877.       procedure clear_footnotes ( lines_we_already_output : integer ) is
  3878.         -- we output the specified number of foot note lines. 
  3879.         -- please do whatever is necessary to prepare for the next page
  3880.         line_we_are_working : heading_or_footing_line_pointer ;
  3881.         line_to_do_next     : heading_or_footing_line_pointer ;
  3882.       begin -- clear_footnotes
  3883.         if lines_we_already_output > 0 then
  3884.           line_we_are_working := Current_Document_Parameters.FootNote_Pointer ;
  3885.           for linen in 1 .. lines_we_already_output loop
  3886.             line_to_do_next     := line_we_are_working.next_line ;
  3887.             freelist_heading.put_onto_free_list ( line_we_are_working ) ;
  3888.             -- this item is added to the free list
  3889.             line_we_are_working := line_to_do_next ;
  3890.           end loop ;
  3891.           Current_Document_Parameters.FootNote_Pointer := line_we_are_working ;
  3892.           Current_Document_Parameters.FootNote_Lines   
  3893.             := Current_Document_Parameters.FootNote_Lines 
  3894.                       - lines_we_already_output ;
  3895.           If Current_Document_Parameters.FootNote_Lines = 0 then
  3896.             Current_Document_Parameters.FootNote_Height := 0 ;
  3897.           else
  3898.             Current_Document_Parameters.FootNote_Height 
  3899.               := Current_Document_Parameters.FootNote_Height
  3900.                         - lines_we_already_output
  3901.                         * Current_Document_Parameters.Page_Heading_Footing_VMI ;
  3902.           end if ;
  3903.         end if ;
  3904.       end clear_footnotes ;
  3905.        
  3906.       Procedure New_Page is
  3907.       begin
  3908.         if (z_smart_printer /= z_smart) or
  3909.            (current_environment.printer_brand = z_cent737) then
  3910.           -- fix for centronics 
  3911.           move_to_vertical_position ( Current_Physical_Parameters.Paper_Length);
  3912.           -- we have to be here on a gotoscreen
  3913.           if current_environment.where_to = to_screen then
  3914.             ot ( extended_cr ) ;
  3915.             for looper in 1 .. 38 loop
  3916.               ot ( extended_minus ) ;
  3917.               ot ( extended_space ) ;
  3918.             end loop ;
  3919.             ot ( extended_cr ) ;
  3920.           end if ;
  3921.         end if ;
  3922.       end new_page ;
  3923.        
  3924.       procedure increment_page_number is
  3925.       begin -- increment_page_number
  3926.         -- Global....Used for Updating Status and Binding Determination
  3927.         --           for odd pages (within Printf)
  3928.         Physical_Page_Number := Physical_Page_Number + 1 ;
  3929.         Current_Document_Parameters.Current_Page_Number
  3930.                         := Current_Document_Parameters.Current_Page_Number + 1 ;
  3931.         if Current_Document_Parameters.Section_Numbering_On then
  3932.           Current_Document_Parameters.Current_Section_Num
  3933.                         := Current_Document_Parameters.Current_Section_Num + 1 ;
  3934.         end if ;
  3935.         if Current_Document_Parameters.Current_Page_Number 
  3936.                 > Current_Environment.Last_Page_To_Print then
  3937.           If output_permitted then
  3938.             -- we must eject the last page
  3939.             execute_printer_command( end_last_page ) ;
  3940.           end if ;
  3941.           -- finish_output_for_a_document ;
  3942.           raise Last_Selected_Page_Printed ;
  3943.         end if;
  3944.       end increment_page_number ;
  3945.        
  3946.     begin -- end_a_page
  3947.       if need_to_start_page then
  3948.         return ;
  3949.       end if ;
  3950.       -- First: We must move to the correct vertical position....
  3951.       -- page number ?
  3952.       if Current_Document_Parameters.Page_Numbering_On 
  3953.       and not Current_Document_Parameters.Number_Page_At_Top then
  3954.         if output_permitted then
  3955.           generate_page_number_line ;
  3956.         end if ;
  3957.         page_number_line_ready := true ;
  3958.       else
  3959.         page_number_line_ready := false ;
  3960.       end if ;
  3961.       --  Bottom_Loc is the last printable vertical position
  3962.       Bottom_Loc  := Current_Physical_Parameters.Paper_Length
  3963.                       - Current_Physical_Parameters.Bottom_Margin ;
  3964.       -- Footer_Loc is where to start the footer
  3965.       --      Note that the page number shares the last line with the
  3966.       --      footer
  3967.       Footer_Loc  := Bottom_Loc - Current_Document_Parameters.Footing_Height ;
  3968.       -- PageNum_Loc is where to put the page number
  3969.       PageNum_Loc := Bottom_Loc - current_vertical_motion_index ;
  3970.                                       -- or ?? - Current_Font.Font_Height ;
  3971.       if page_number_line_ready 
  3972.       and then footer_loc = bottom_loc then
  3973.         -- we must add in a line...
  3974.         Footer_Loc  := PageNum_Loc ;
  3975.       end if ;
  3976.       -- FootNote_And_Footer_Loc is location to start the footer information
  3977.       FootNote_And_Footer_Loc  := Footer_Loc
  3978.                       - Current_Document_Parameters.FootNote_Height ;
  3979.       -- Now, however, if FootNote_And_Footer_Loc and Bottom_Loc are 
  3980.       -- identical, then we need to simply work page numbering
  3981.       if ( current_physical_parameters.Printing_Left_Side 
  3982.       or ( current_physical_parameters.real_center_right = 0) ) then 
  3983.         -- first column or not double column and we are printing
  3984.         -- this is either first col of two, or single column
  3985.         -- we have to check this out even if not output_permitted because
  3986.         -- we might have a partial foot note
  3987.         If Output_Permitted then 
  3988.           -- we are outputting now 
  3989.           -- now, move
  3990.           If Bottom_Loc /= FootNote_And_Footer_Loc then
  3991.             -- we have to do work on the bottom of a page
  3992.             if Current_Document_Parameters.Footing_Height 
  3993.                       + Current_Document_Parameters.FootNote_Height = 0 then
  3994.               -- easiest, just a page number
  3995.               If PageNum_Loc > Printer_Vertical_Position
  3996.                                            + current_vertical_motion_index
  3997.               then
  3998.                 move_to_vertical_position(PageNum_Loc);
  3999.               -- else we squeezed an extra line on the page, and therefore
  4000.               -- want to simply print whereever we are now...
  4001.               else
  4002.                 move_down_a_line ( 2 ) ;
  4003.               end if ;
  4004.               output_a_line ( page_number_line ) ;
  4005.             else
  4006.               -- at least a footer or foot note, possibly also a page number
  4007.               moving_vmi:=Current_Document_Parameters.Page_Heading_Footing_VMI ;
  4008.               lines_we_can_output := 
  4009.                           Current_Document_Parameters.FootNote_Lines ;
  4010.               if lines_we_can_output > 0 then
  4011.                 lines_we_can_output := lines_we_can_output + 2 ;
  4012.                 -- take into account the two leading lines...
  4013.               end if ;
  4014.               If FootNote_And_Footer_Loc > Printer_Vertical_Position
  4015.                                            + current_vertical_motion_index
  4016.               then
  4017.                 move_to_vertical_position(FootNote_And_Footer_Loc);
  4018.               elsif FootNote_And_Footer_Loc < Printer_Vertical_Position
  4019.                                                - moving_vmi then
  4020.                 -- we get here if we cannot fit the entire footnote onto
  4021.                 -- the page, even if we add one line to the length of the
  4022.                 -- page......
  4023.                 Lines_We_Can_Output := ( Printer_Vertical_Position 
  4024.                                           - Footer_Loc ) / moving_vmi ;
  4025.                 if lines_we_can_output < 3 then
  4026.                   lines_we_can_output := 0 ; 
  4027.                   -- because it takes two lines to set up the foot note
  4028.                 end if ;
  4029.                 move_down_a_line ( 2 ) ;
  4030.               -- else we can fit the entire footnote on the page..although
  4031.               --      we might be forced to add a line to do it...
  4032.               else
  4033.                 move_down_a_line ( 2 ) ;
  4034.               end if ;
  4035.               if lines_we_can_output > 0 then
  4036.                 -- we can do something with the foot notes...
  4037.                 old_vmi := current_vertical_motion_index ;
  4038.                 execute_printer_command ( set_vmi , moving_vmi ) ;
  4039.                 generate_one_inch_line  ( Temporary_Line       ) ;
  4040.                 output_a_line ( Temporary_Line ) ;
  4041.                 move_down_a_line ( 2 ) ;
  4042.                 lines_we_can_output := lines_we_can_output - 2 ;
  4043.                 output_line_set ( Current_Document_Parameters.FootNote_Pointer ,
  4044.                                   Lines_We_Can_Output ,
  4045.                                   false ,
  4046.                                   null  ,
  4047.                                   false ,
  4048.                                   at_bottom ) ;
  4049.                 clear_footnotes ( Lines_we_can_output ) ;
  4050.                 execute_printer_command ( set_vmi , old_vmi    ) ;
  4051.               end if ;
  4052.               -- now, we are here and done with footnotes.....
  4053.               if Current_Document_Parameters.Footing_Lines > 0 then
  4054.                 output_line_set ( Current_Document_Parameters.Footing_Pointer ,
  4055.                                   Current_Document_Parameters.Footing_Lines   ,
  4056.                                   page_number_line_ready ,
  4057.                                   page_number_line ,
  4058.                                   true  ,
  4059.                                   at_top ) ;
  4060.               elsif page_number_line_ready then
  4061.                 output_a_line ( page_number_line ) ;
  4062.               end if ;
  4063.             end if ;
  4064.             -- end of doing work at the bottom of a page
  4065.           -- else there is no page number, footer, or foot note
  4066.           end if ;
  4067.         else
  4068.           -- output is not permitted
  4069.           If Current_Document_Parameters.FootNote_Lines > 0 then
  4070.             moving_vmi:=Current_Document_Parameters.Page_Heading_Footing_VMI ;
  4071.             lines_we_can_output:=Current_Document_Parameters.FootNote_Lines + 2;
  4072.               -- take into account the two leading lines...
  4073.             if FootNote_And_Footer_Loc < Printer_Vertical_Position
  4074.                                              - moving_vmi then
  4075.               -- we get here if we cannot fit the entire footnote onto
  4076.               -- the page, even if we add one line to the length of the
  4077.               -- page......
  4078.               Lines_We_Can_Output := ( Printer_Vertical_Position 
  4079.                                           - Footer_Loc ) / moving_vmi ;
  4080.               if lines_we_can_output < 3 then
  4081.                 lines_we_can_output := 0 ; 
  4082.                 -- because it takes two lines to set up the foot note
  4083.               end if ;
  4084.             -- else we can fit the entire footnote on the page..although
  4085.             --      we might be forced to add a line to do it...
  4086.             end if ;
  4087.             if lines_we_can_output > 0 then
  4088.               -- we can do something with the foot notes...
  4089.               lines_we_can_output := lines_we_can_output - 2 ;
  4090.               clear_footnotes ( Lines_we_can_output ) ;
  4091.             end if ;
  4092.           end if ; -- output not permitted but we had foot notes to work 
  4093.         end if ;
  4094.       -- else we are on the right half of a double column page
  4095.       end if ;  
  4096.       if current_physical_parameters.real_center_right = 0 
  4097.       or else not current_physical_parameters.Printing_Left_Side then 
  4098.         -- here when we have finished a page, either a normal page or
  4099.         -- else the right side of a dual column page
  4100.         if current_environment.where_to /= to_screen then
  4101.           UpDate_Status ;
  4102.         end if;
  4103.         if Output_Permitted then
  4104.           new_page ; 
  4105.         end if ;
  4106.         Increment_Page_Number ;
  4107.       end if ;
  4108.       if current_physical_parameters.real_center_right /= 0 then 
  4109.         -- we are doing double column work
  4110.         if current_physical_parameters.Printing_Left_Side then 
  4111.           -- we were printing left side
  4112.           if output_permitted then
  4113.             move_to_vertical_position(0);
  4114.           else
  4115.             Printer_Vertical_Position := 0 ;
  4116.           end if ;
  4117.         else
  4118.           -- we were printing right side 
  4119.           null ;
  4120.         end if ;
  4121.         current_physical_parameters.Printing_Left_Side 
  4122.                     := not current_physical_parameters.Printing_Left_Side ;
  4123.         if current_physical_parameters.Printing_Left_Side then
  4124.           current_Physical_Parameters.left_margin 
  4125.                     := current_physical_parameters.real_left ;
  4126.           current_Physical_Parameters.right_margin 
  4127.                     := current_physical_parameters.real_center_right ;
  4128.         else
  4129.           current_Physical_Parameters.left_margin 
  4130.                     := current_physical_parameters.real_center_left ;
  4131.           current_Physical_Parameters.right_margin 
  4132.                     := current_physical_parameters.real_right ;
  4133.         end if ;
  4134.         set_line_information ;
  4135.       end if ; -- end of double column work ...
  4136.       Need_To_Start_Page := true ;
  4137.     end end_a_page ;
  4138.  
  4139.     Procedure Pstring_To_Output_Line ( Ps : pstring ;
  4140.                                        OtLine : in out output_line_pointer ) is
  4141.       -- change a standard pstring into an acceptable output line
  4142.       tmp_holder : output_line_pointer ;
  4143.       pstring_temporary_invalid_breaks : boolean_array    ;
  4144.       Save_Input_Line        : Input_Line_Type  := Input_Line        ;
  4145.       Save_Input_Line_Length : Input_Line_Index := Input_Line_Length ;
  4146.     begin -- pstring_to_output_line
  4147.       -- first, save the current output line information...
  4148.       tmp_holder          := waiting_output_line ;
  4149.       waiting_output_line := OtLine              ;
  4150.       OtLine              := tmp_holder          ;
  4151.       pstring_temporary_invalid_breaks := waiting_output_invalid_breaks ;
  4152.       -- now, move over new data to input line
  4153.       input_line_length := length ( ps ) ;
  4154.       for posn in 1 .. input_line_length loop
  4155.         input_line ( posn ) := 
  4156.                      extended_character ( character'pos ( ps.data ( posn ) ) ) ;
  4157.       end loop ;
  4158.       -- and move to output line
  4159.       input_line_to_output_line ;
  4160.       -- and then switch back
  4161.       -- and since we do not have any justification, simply ignore any breaks..
  4162.       tmp_holder          := waiting_output_line    ;
  4163.       waiting_output_line := OtLine                 ;
  4164.       OtLine              := tmp_holder             ;
  4165.       Input_Line          := Save_Input_Line        ;
  4166.       Input_Line_Length   := Save_Input_Line_Length ;
  4167.     end pstring_to_output_line ;
  4168.      
  4169.     procedure send_input_text_to_output_device is
  4170.       -- we have an input line and filling is off
  4171.     begin -- send_input_text_to_output_device
  4172.       output_a_line ( waiting_output_line ) ;
  4173.     end send_input_text_to_output_device ;
  4174.        
  4175.     procedure modify_a_line ( output_line : in out output_line_pointer ) is
  4176.       len : horizontal_measurement ;
  4177.       new_pos : integer ;
  4178.       -- Integer in case they center crazily...
  4179.       rightmost_text_position     : horizontal_measurement 
  4180.                           := current_physical_parameters.paper_width
  4181.                            - current_physical_parameters.right_margin          ;
  4182.       -- centering does not take into account the subparagraph or goleft
  4183.     begin -- modify_a_line
  4184.       case current_formatting_parameters.line_modification is
  4185.         when nothing       => null ;
  4186.         when center_mod    => 
  4187.                   len := output_line.stop_position 
  4188.                               - output_line.start_position ;
  4189.                   new_pos := leftmost_normal_position
  4190.                              -- left margin
  4191.                              + ( rightmost_text_position
  4192.                                -- Plus Right Boundry
  4193.                                - leftmost_normal_position
  4194.                                -- Minus Left Boundry, giving actual
  4195.                                -- potential line length
  4196.                                - len )
  4197.                                -- Minus used length, 
  4198.                                / 2 ; 
  4199.                                -- divided by 2
  4200.                   if new_pos > 0 then
  4201.                     output_line.start_position := new_pos ;
  4202.                   else
  4203.                     output_line.start_position := 1 ;
  4204.                   end if ;
  4205.                   output_line.stop_position 
  4206.                                   := output_line.start_position
  4207.                                         + len ;
  4208.                   output_line.justify_to
  4209.                                   := output_line.stop_position ;
  4210.                   output_line.first_justify  := waiting_output_line
  4211.                                         .character_count + 1 ; 
  4212.         when right_justify => 
  4213.                   len := output_line.stop_position 
  4214.                               - output_line.start_position ;
  4215.                   output_line.stop_position 
  4216.                                   := rightmost_text_position ;
  4217.                   output_line.start_position 
  4218.                                   := rightmost_text_position - len ;
  4219.                   output_line.justify_to
  4220.                                   := rightmost_text_position ;
  4221.                   output_line.first_justify  := waiting_output_line
  4222.                                         .character_count + 1 ; 
  4223.         when to_left_margin=>
  4224.                   len := output_line.stop_position 
  4225.                               - output_line.start_position ;
  4226.                   output_line.start_position 
  4227.                                   := leftmost_edge_position ;
  4228.                   output_line.stop_position 
  4229.                                   := leftmost_edge_position + len ;
  4230.                   output_line.justify_to
  4231.                                   := rightmost_text_position ;
  4232.                   output_line.first_justify  := waiting_output_line
  4233.                                         .character_count + 1 ; 
  4234.       end case ;
  4235.       -- and adjust modification if necessary
  4236.       if current_formatting_parameters.line_modification /= nothing
  4237.       and then current_formatting_parameters.modification_status
  4238.                           = do_while_counting then
  4239.         current_formatting_parameters.modify_to_do
  4240.                   := current_formatting_parameters.modify_to_do - 1 ;
  4241.         if current_formatting_parameters.modify_to_do = 0 then
  4242.           -- we have just finished...
  4243.           Current_Formatting_Parameters.Filling_On 
  4244.                         := current_formatting_parameters.Fill_Before_Special ;
  4245.           Current_Formatting_Parameters.Justification_On 
  4246.                         := current_formatting_parameters.Just_Before_Special ;
  4247.           Current_Formatting_Parameters.Modification_Status := Off     ;
  4248.           Current_Formatting_Parameters.Line_Modification   := Nothing ;
  4249.         end if ;
  4250.       end if ;
  4251.     end modify_a_line ;
  4252.              
  4253.     procedure set_line_data( LineInfo : in out heading_or_footing_line_pointer ;
  4254.                              LineData : in output_line_type ) is
  4255.     begin -- set_line_data
  4256.       LineInfo.Data := LineData ;
  4257.     end set_line_data ;
  4258.      
  4259.     procedure set_next_ptr ( LineInfo : heading_or_footing_line_pointer ) is
  4260.     begin -- set_next_ptr
  4261.       LineInfo.Next_Line := freelist_heading.get_from_free_list ;
  4262.     end set_next_ptr ;
  4263.      
  4264.     function next_line_ptr ( LineInfo : heading_or_footing_line_pointer )
  4265.                              return heading_or_footing_line_pointer is
  4266.     begin -- next_line_ptr
  4267.       return LineInfo.next_line ;
  4268.     end next_line_ptr ;
  4269.     
  4270.     function return_line_data(LineInfo : in heading_or_footing_line_pointer)
  4271.                              return output_line_type is
  4272.     begin -- return_line_data
  4273.       return LineInfo.data ;
  4274.     end return_line_data ;
  4275.      
  4276.     procedure initialize_print_out_for_a_new_document        is
  4277.     begin -- initialize_print_out_for_a_new_document 
  4278.       if current_environment.where_to = to_screen then
  4279.         start_console_page ;
  4280.       else
  4281.         -- for output to text file for later editing
  4282.         Console_Last   := 0 ;
  4283.         Console_Length := 0 ;
  4284.         Console_Line_Number := 0 ;
  4285.       end if ;
  4286.       -- Now, do private items...
  4287.       Printer_Position          := 0 ;
  4288.       Printer_Vertical_Position := 0 ;
  4289.       -- console items set by start_console_page
  4290.       page_number_line.all       := blank_output_line ;
  4291.       page_number_position       := 0                 ;
  4292.       temporary_line.all         := blank_output_line ;
  4293.       waiting_output_line.all    := blank_output_line ;
  4294.       Points_Moved_Since_Text_Sent_To_Output_Device  := 0  ;
  4295.     end initialize_print_out_for_a_new_document ;
  4296.    
  4297.     procedure finish_print_out_for_an_old_document           is
  4298.       -- temp : boolean ;
  4299.     begin -- finish_print_out_for_an_old_document 
  4300.       clear_a_list ( Current_Document_Parameters.FootNote_Pointer ) ;
  4301.         -- that is possible if only selected pages were requested...
  4302.       clear_a_list ( Current_Document_Parameters.Footing_Pointer ) ;
  4303.       clear_a_list ( Current_Document_Parameters.Heading_Pointer ) ;
  4304.     end finish_print_out_for_an_old_document ;
  4305.      
  4306.     procedure close_print_out           is
  4307.       temp : boolean ;
  4308.     begin -- close_print_out 
  4309.       null ; -- need to release that memory...
  4310.     end close_print_out ;
  4311.      
  4312.   begin -- print_out ;
  4313.     page_number_line           := new output_line_type ;
  4314.     temporary_line             := new output_line_type ;
  4315.   end print_out  ;
  4316.       
  4317.   --$$$- PRNTOUT
  4318.  
  4319. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4320. --prntmsc
  4321. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4322.  
  4323.   --$$$+ PRNTMSC
  4324.     
  4325.   --
  4326.   -- File 0xx
  4327.   --
  4328.   -- Formatter Written By Robert S. Cymbalski
  4329.   --                      Science Applications International Corporation
  4330.   --                      Energy Systems Group
  4331.   --                      Ada Software Development Project Team
  4332.   --                      2280 U.S. Highway 19 North, Suite 120
  4333.   --                      Clearwater, Florida  33575
  4334.   --
  4335.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  4336.   --
  4337.    
  4338.   with direct_io       ;
  4339.    
  4340.   with text_io         ;
  4341.    
  4342.   with io_exceptions   ;
  4343.    
  4344.   with string_library  ;
  4345.   use  string_library  ;
  4346.     
  4347.   with basic_io_system ;
  4348.    
  4349.   with crt_windows     ;
  4350.   use  crt_windows     ;
  4351.     
  4352.   with Wordp_Globals   ;
  4353.   use  Wordp_Globals   ;
  4354.    
  4355.   with name_tree ;
  4356.   use  name_tree ;
  4357.    
  4358.   with Printer_globals ;
  4359.   use  printer_globals ;
  4360.    
  4361.   with printf    ;
  4362.   use  printf    ;
  4363.    
  4364.   with print_in_to_out ;
  4365.   use  print_in_to_out ;
  4366.    
  4367.   with print_out ;
  4368.   use  print_out ;
  4369.    
  4370.   Package Printer_Misc is
  4371.      
  4372.     Commands_Were_Processed_Just_Now : boolean ;
  4373.       -- set by get_line.  If get_line has to process any commands while
  4374.       -- looking for new text, this item is set true, otherwise, it is
  4375.       -- set false
  4376.        
  4377.     type vertical_movement_request_type is
  4378.                 ( stay_on_this_line , 
  4379.                   move_forward_on_page ,
  4380.                   move_backward_on_page ,
  4381.                   move_to_absolute_position ) ;
  4382.                    
  4383.     end_of_main_input_file : boolean ;
  4384.     ready_to_stop          : boolean ;
  4385.     processing_comment_area: boolean ;
  4386.     amount_waiting_to_move_vertically_before_line : vertical_measurement ;
  4387.     kind_of_move_before_line                 : vertical_movement_request_type ;
  4388.     amount_waiting_to_move_vertically_after_line  : vertical_measurement ;
  4389.     kind_of_move_after_line                  : vertical_movement_request_type ;
  4390.     text_waiting_inside_filled_paragraph : boolean ;
  4391.     tab_requested_to_position : horizontal_measurement ;
  4392.     just_did_tab_command      : boolean ;
  4393.     specifically_requested_to_remain_on_this_line : boolean ;
  4394.     max_switches : constant integer := 20 ;
  4395.      
  4396.     type switch_list is array ( 1 .. max_switches ) of boolean ;
  4397.      
  4398.     switches : switch_list ;
  4399.      
  4400.     command_word : a_tree_name_string ;
  4401.      
  4402.     command_tree : name_node := null ; 
  4403.      
  4404.     -- types for a command line parse
  4405.      
  4406.     type numeric_contents_type is ( no_numeric_contents  ,
  4407.                                     absolute_numeric     ,
  4408.                                     positive_rel_numeric ,
  4409.                                     negative_rel_numeric ) ;
  4410.                                      
  4411.     type modifier_type is         ( no_modifier          ,
  4412.                                     default_modifier     ,
  4413.                                     on_modifier          ,
  4414.                                     off_modifier         ,
  4415.                                     toggle_modifier      ,
  4416.                                     top_modifier         ,
  4417.                                     bottom_modifier      ,
  4418.                                     left_modifier        ,
  4419.                                     right_modifier       ,
  4420.                                     center_modifier      ,
  4421.                                     alternating_modifier ) ;
  4422.                                      
  4423.     -- now, we have the results of a command line parse
  4424.      
  4425.     command_node        : name_node ;
  4426.     command             : text_formatter_command        ;
  4427.                                 -- that is the command which was specified
  4428.     user_command_number : integer                       ;
  4429.                                 -- that is a number that signifies the 
  4430.                                 -- special number a user can associate 
  4431.                                 -- with user defined commands
  4432.     numeric_contents    : numeric_contents_type         ;
  4433.                                 -- this tells us if we have any numeric
  4434.                                 -- parameters, and if so whether it is
  4435.                                 -- absolute, positive relative, or
  4436.                                 -- negative relative.
  4437.     numeric_value       : integer                       ;
  4438.                                 -- only defined if numeric_contents is
  4439.                                 -- not no_numeric_contents 
  4440.     modifier_one        : modifier_type                 ;
  4441.                                 -- if they have an alphabetic modifier,
  4442.                                 -- what is its value.... none, 
  4443.                                 -- ON, OFF, or TOGGLE
  4444.                                 -- (can be abbr. to first 2 letters )
  4445.     modifier_two        : modifier_type                 ;
  4446.                                 -- if they have an alphabetic modifier,
  4447.                                 -- what is its value.... none, 
  4448.                                 -- ON, OFF, or TOGGLE
  4449.                                 -- (can be abbr. to first 2 letters )
  4450.     text_parameters     : pstring                       ;
  4451.                                 -- if text parameters follow, 
  4452.                                 -- ( noted by a ' or " as the
  4453.                                 -- signal ), then it is loaded
  4454.                                 -- into text_parameters
  4455.                                 -- trailing blanks are NOT significant
  4456.      
  4457.     Next_Position_To_Work : Input_Line_Index ;
  4458.      
  4459.     -- end of the results of a command line parse
  4460.      
  4461.     exactly_one : constant boolean := true ;
  4462.      
  4463.     type an_allowed_option is ( o_any_numeric ,
  4464.                                 o_abs_numeric ,
  4465.                                 o_rel_numeric ,
  4466.                                 o_on_off      ,
  4467.                                 o_off         ,
  4468.                                 o_toggle      ,
  4469.                                 o_top_bottom  ,
  4470.                                 o_l_r_c_alt   ,
  4471.                                 o_text_param  ,
  4472.                                 o_none        ) ;
  4473.      
  4474.     Index_Output_File   : Text_IO.File_Type ;
  4475.      
  4476.     Index_File_Is_Open  : Boolean ;
  4477.      
  4478.     Index_File_Name     : Ascii_Text_File_Name ;
  4479.      
  4480.     -- now for some variable data
  4481.      
  4482.     max_user_variables : constant integer := 20 ;
  4483.      
  4484.     user_variable_data : array ( 1 .. max_user_variables ) of pstring ;
  4485.      
  4486.     function user_interrupt return boolean ;
  4487.      
  4488.     function select_font( New_Font_Number : in Font_Number ) return boolean ;
  4489.         
  4490.     procedure set_fixed_font ( Pitch : Horizontal_Measurement ) ;
  4491.    
  4492.     Procedure Parse_Input_Command_Line ;
  4493.    
  4494.     function map_up ( c : extended_character ) return extended_character ;
  4495.      
  4496.     Function If_Function return boolean ;
  4497.        
  4498.     -- Now, for some input line processing routines
  4499.      
  4500.     procedure initialize_printer_misc_for_a_new_document     ;
  4501.    
  4502.     procedure finish_printer_misc_for_an_old_document        ;
  4503.    
  4504.     procedure close_printer_misc ;
  4505.      
  4506.     --###--RSC02
  4507.    
  4508.   end Printer_Misc ;
  4509.    
  4510.   Package Body Printer_Misc is
  4511.    
  4512.     package font_io is new direct_io( font_type ) ;
  4513.      
  4514.     font_input_file : font_io.file_type ;
  4515.      
  4516.     function user_interrupt return boolean is
  4517.       cc : character ;
  4518.     begin -- user_interrupt
  4519.       if basic_io_system.key_is_pressed then
  4520.         loop
  4521.           goto_line_column ( master_window , 23 , 1 ) ;
  4522.           cc := char_within_range_or_abort ( ' ' , ' ' , '~' ) ;
  4523.           clear_end_of_screen ( master_window , 23 , 1 ) ;
  4524.           case cc is
  4525.             when 'S'|'s'=> clear_end_of_screen ( master_window , 23 , 1 ) ;
  4526.                            goto_line_column ( master_window , 23 , 1 ) ;
  4527.                            put("User Pause.  Tap any character to continue...");
  4528.                            cc := char_within_range_or_abort ( ' ' ,
  4529.                                                               ascii.nul ,
  4530.                                                               ascii.del ) ;
  4531.                            clear_end_of_screen ( master_window , 23 , 1 ) ;
  4532.             when 'H'|'h'=> raise Users_Requested_Abort ;
  4533.             when others => null ; -- 
  4534.           end case ;
  4535.         exit when not basic_io_system.key_is_pressed ;
  4536.         end loop ;
  4537.         return false ;
  4538.       else
  4539.         return false ;
  4540.       end if ;
  4541.     end user_interrupt ;
  4542.      
  4543.     Procedure Skip_blanks is
  4544.     begin  -- skip_blanks
  4545.       while ( Next_Position_To_Work < Input_Line_Length ) 
  4546.       and   ( Input_Line(Next_Position_To_Work) = extended_space ) loop
  4547.         Next_Position_To_Work := Next_Position_To_Work + 1 ;
  4548.       end loop ;
  4549.     end skip_blanks ;
  4550.      
  4551.     Procedure Get_Command is
  4552.       -- note that get_command requires that a space be the last character
  4553.       -- of all input lines....
  4554.       Command_Word_Place : integer := 1 ;
  4555.     begin  -- get_command
  4556.       Command_Word := blank_tree_name_string ;
  4557.       while Input_Line(Next_Position_To_Work) /= extended_space 
  4558.       and then command_word_place <= a_tree_name_string_length loop
  4559.         command_word(Command_Word_Place) := 
  4560.                 character'val( Input_Line(Next_Position_To_Work) ) ;
  4561.         Command_Word_Place := Command_Word_Place + 1 ;
  4562.         Next_Position_To_Work := Next_Position_To_Work + 1 ;
  4563.       end loop ;
  4564.       if input_line(next_position_to_work) /= extended_space then
  4565.         -- they had a really long name
  4566.         loop
  4567.           next_position_to_work := next_position_to_work + 1 ;
  4568.         exit when input_line(next_position_to_work) = extended_space ;
  4569.         end loop ;
  4570.       end if ;
  4571.       command_node := query( command_word , command_tree ) ;
  4572.       if command_node = null then
  4573.         command := illegal_command ;
  4574.       else
  4575.         command := command_node.printer_command ;
  4576.         user_command_number := command_node.other_info ;
  4577.       end if ;
  4578.       skip_blanks ;
  4579.     end get_command ;
  4580.      
  4581.     Function Translate_Current_Work_Character_To_Integer return integer is
  4582.       cc : extended_character := Input_Line ( Next_Position_To_Work ) ;
  4583.     begin  -- translate_current_work_character_to_integer
  4584.       if ( cc <= extended_nine ) and ( cc >= extended_zero ) then
  4585.         return integer( cc - extended_zero ) ;
  4586.       else
  4587.         return -1 ;
  4588.       end if ;
  4589.     end translate_current_work_character_to_integer ;
  4590.      
  4591.     function map_up ( c : extended_character ) return extended_character is
  4592.     begin -- map_up
  4593.       if c >= extended_lc_a
  4594.       and then c <= extended_lc_z then
  4595.         return c - extended_lc_a + extended_uc_a ;
  4596.       else
  4597.         return c ;
  4598.       end if ;
  4599.     end map_up ;
  4600.      
  4601.     procedure work_text_string is
  4602.       -- they started a string with a leading item....move it over
  4603.       break_character : extended_character ;
  4604.       new_char        : extended_character ;
  4605.       next_place      : integer := 0 ;
  4606.     begin -- work_text_string
  4607.       if length(text_parameters) > 0 then
  4608.         -- we already have an input string....
  4609.         command_error( "Multiple Text Parameters Not Allowed." ,
  4610.                        true , next_position_to_work ) ;
  4611.       else
  4612.         break_character := Input_Line ( Next_Position_To_Work ) ;
  4613.         loop
  4614.           next_position_to_work := next_position_to_work + 1 ;
  4615.         exit when next_position_to_work > input_line_length ;
  4616.           new_char := Input_Line ( Next_Position_To_Work ) ;
  4617.         exit when new_char = break_character ;
  4618.           next_place := next_place + 1 ;
  4619.           text_parameters.data ( next_place ) 
  4620.                 := character'val ( new_char ) ;
  4621.         end loop ;
  4622.         set_length ( text_parameters , next_place ) ;
  4623.         next_position_to_work := next_position_to_work + 1 ;
  4624.         skip_blanks ;
  4625.       end if ;
  4626.     end work_text_string ;
  4627.        
  4628.     function work_number return integer is
  4629.       -- look at the number which starts at the current position and
  4630.       -- turn it into an integer.  If a number is not here, then 
  4631.       -- signal with an error message and return a ( -1 ) ;
  4632.       working_number : integer 
  4633.                   := translate_current_work_character_to_integer ;
  4634.       temp_number    : integer := working_number ;
  4635.     begin -- work_number 
  4636.       if working_number < 0 then
  4637.         -- error because it should be a number 
  4638.         command_error ( "Expecting Number Here.",true, next_position_to_work ) ;
  4639.       end if ;
  4640.       loop
  4641.         next_position_to_work := next_position_to_work + 1 ;
  4642.         working_number := translate_current_work_character_to_integer ;
  4643.       exit when working_number < 0 ;
  4644.         if temp_number > integer'last / 10 - 9 then
  4645.           command_error ( "Number Too Large.", true , next_position_to_work ) ;
  4646.         else
  4647.           temp_number := temp_number * 10 + working_number ;
  4648.         end if ;
  4649.       end loop ;
  4650.       -- we only get here on good number
  4651.       return temp_number ;
  4652.     end work_number ;
  4653.      
  4654.     procedure work_numeric_part ( num_type : in numeric_contents_type ) is
  4655.       temp_number : integer ;
  4656.       number_start : input_line_index ;
  4657.     begin -- work_numeric_part
  4658.       number_start := next_position_to_work ;
  4659.       if num_type /= absolute_numeric then
  4660.         -- must skip the sign...
  4661.         Next_Position_To_Work := Next_Position_To_Work + 1 ;
  4662.         skip_blanks ;
  4663.       end if ;
  4664.       temp_number := work_number ;
  4665.       -- a good one to work 
  4666.       if numeric_contents /= no_numeric_contents
  4667.       then
  4668.         -- we have defined two fields....
  4669.         command_error ( "Only One Numeric Field may appear in a command.",
  4670.                         true , number_start ) ;
  4671.       else
  4672.         numeric_contents    := num_type ;
  4673.         numeric_value       := temp_number ;
  4674.       end if ;
  4675.       skip_blanks ;
  4676.     end work_numeric_part ;
  4677.        
  4678.     Function If_Function return boolean is
  4679.     --###--RSC02
  4680.     begin  -- If_Function
  4681.       --###--RSC02
  4682.       return true;
  4683.     end If_Function ;
  4684.      
  4685.     Procedure Parse_Input_Command_Line is
  4686.       this_char : extended_character ;
  4687.       cc        : character          ;
  4688.      
  4689.       Procedure compress_input_line ( only_right : in boolean ) is
  4690.         start_ind  : integer := 1 ;
  4691.         ending_ind : integer := input_line_length ;
  4692.       begin
  4693.         if not only_right then
  4694.           -- we are to compress both sides...
  4695.           While start_ind <= ending_ind
  4696.           and then Input_Line(start_ind) = extended_space loop
  4697.             start_ind := start_ind + 1 ;
  4698.           end loop ;
  4699.         end if ;
  4700.         while ending_ind >= start_ind 
  4701.         and then Input_Line(ending_ind) = extended_space loop
  4702.           ending_ind := ending_ind - 1 ;
  4703.         end loop ;
  4704.         if start_ind > ending_ind then
  4705.           Input_Line_Length := 0 ;
  4706.         else
  4707.           if start_ind > 1 then
  4708.             for posn in start_ind .. ending_ind loop
  4709.               Input_Line ( posn - start_ind + 1 ) := Input_Line ( posn ) ;
  4710.             end loop ;
  4711.           end if ;
  4712.           Input_Line_Length := ending_ind - start_ind + 1 ;
  4713.         end if ;
  4714.       end compress_input_line ;
  4715.  
  4716.       procedure work_unquoted_text_string is
  4717.         -- we have a string but it is unquoted
  4718.         new_char        : extended_character ;
  4719.         next_place      : integer := 0 ;
  4720.       begin -- work_unquoted_text_string
  4721.         if length(text_parameters) > 0 then
  4722.           -- we already have an input string....
  4723.           command_error( "Unrecognized Parameter." , true 
  4724.                                                    , next_position_to_work ) ;
  4725.         else
  4726.           -- need to get rid of trailing blanks, just like in prntwork
  4727.           compress_input_line ( True ) ;
  4728.           loop
  4729.           exit when next_position_to_work > input_line_length ;
  4730.             new_char := Input_Line ( Next_Position_To_Work ) ;
  4731.             next_place := next_place + 1 ;
  4732.             text_parameters.data ( next_place ) := character'val ( new_char ) ;
  4733.             next_position_to_work := next_position_to_work + 1 ;
  4734.           end loop ;
  4735.           set_length ( text_parameters , next_place ) ;
  4736.         end if ;
  4737.         -- put ( " Text Parameters => """ ) ;
  4738.         -- put ( text_parameters ) ;
  4739.         -- put ( """" ) ;
  4740.         -- put ( ascii.cr ) ;
  4741.       end work_unquoted_text_string ;
  4742.        
  4743.       procedure work_modifier is
  4744.         -- we have an alphabetic item, so we are assuming that it is
  4745.         -- a modifier
  4746.         start_place : input_line_index ;
  4747.         new_modifier: modifier_type    ;
  4748.         ec : extended_character ;
  4749.         cc : character ;
  4750.        
  4751.         procedure unknown_modifier is
  4752.         begin -- unknown_modifier 
  4753.           command_error ( "Unrecognized command parameter." , true , 
  4754.                                                               start_place ) ;
  4755.         end unknown_modifier ;
  4756.          
  4757.       begin -- work_modifier
  4758.         -- this routine is all in line because it is called LOTS of times
  4759.         start_place := next_position_to_work ;
  4760.         ec := Input_Line ( Next_Position_To_Work ) ;
  4761.         if ec > 128 then
  4762.           cc := ascii.del ;
  4763.         else
  4764.           cc := character'val ( ec ) ;
  4765.         end if ;
  4766.         Next_Position_To_Work := Next_Position_To_Work + 1 ;
  4767.         case cc is
  4768.           when 'a' | 'A' => -- can be alternating
  4769.                             new_modifier := alternating_modifier ;
  4770.           when 'b' | 'B' => -- can be Bottom 
  4771.                             new_modifier := bottom_modifier      ;
  4772.           when 'c' | 'C' => -- can be center
  4773.                             new_modifier := center_modifier      ;
  4774.           -- when 'd' | 'D' => -- can be default
  4775.                             -- new_modifier := default_modifier     ;
  4776.           when 'l' | 'L' => -- can be Left
  4777.                             new_modifier := left_modifier        ;
  4778.           when 'o' | 'O' => -- can be ON , OFF 
  4779.                             ec := Input_Line ( Next_Position_To_Work ) ;
  4780.                             if ec > 128 then
  4781.                               cc := ascii.del ;
  4782.                             else
  4783.                               cc := character'val ( ec ) ;
  4784.                             end if ;
  4785.                             if cc = 'n' or cc = 'N' then
  4786.                               new_modifier := on_modifier        ;
  4787.                             elsif cc = 'f' or cc = 'F' then
  4788.                               new_modifier := off_modifier       ;
  4789.                             else
  4790.                               unknown_modifier                   ;
  4791.                             end if ;
  4792.           when 'r' | 'R' => -- can be right 
  4793.                             new_modifier := right_modifier       ;
  4794.           when 't' | 'T' => -- can be Toggle , Top
  4795.                             ec := Input_Line ( Next_Position_To_Work ) ;
  4796.                             if ec > 128 then
  4797.                               cc := ascii.del ;
  4798.                             else
  4799.                               cc := character'val ( ec ) ;
  4800.                             end if ;
  4801.                             if cc = 'o' or cc = 'O' then
  4802.                               Next_Position_To_Work:=Next_Position_To_Work + 1 ;
  4803.                               -- the increment of next_position is guaranteed to
  4804.                               -- work because we always know that the last char
  4805.                               -- on any line is a space...
  4806.                               ec := Input_Line ( Next_Position_To_Work ) ;
  4807.                               if ec > 128 then
  4808.                                 cc := ascii.del ;
  4809.                               else
  4810.                                 cc := character'val ( ec ) ;
  4811.                               end if ;
  4812.                               if cc = 'g' or cc = 'G' then
  4813.                                 new_modifier := toggle_modifier    ;
  4814.                               elsif cc = 'p' or cc = 'P' then
  4815.                                 new_modifier := top_modifier       ;
  4816.                               else
  4817.                                 unknown_modifier                   ;
  4818.                               end if ;
  4819.                             else
  4820.                               unknown_modifier             ;
  4821.                             end if ;
  4822.           when others    => unknown_modifier ; -- must be an error
  4823.         end case ;
  4824.         if modifier_one = no_modifier then
  4825.           modifier_one := new_modifier ;
  4826.         else
  4827.           if modifier_two = no_modifier then
  4828.             modifier_two := new_modifier ;
  4829.           else
  4830.             command_error ( "Too many command parameters." , true , 
  4831.                                                              start_place ) ;
  4832.           end if ;
  4833.         end if ;
  4834.         -- now, we need to scan until we hit a space
  4835.         loop
  4836.         exit when Input_Line ( Next_Position_To_Work ) = extended_space ;
  4837.           Next_Position_To_Work := Next_Position_To_Work + 1 ;
  4838.         end loop ;
  4839.         skip_blanks ;
  4840.       end work_modifier ;
  4841.        
  4842.     begin  -- Parse_Input_Command_Line
  4843.       -- make sure that the line ends in a space
  4844.       if input_line_length < max_line_length then
  4845.         input_line_length := input_line_length + 1 ;
  4846.       end if ;
  4847.       Input_Line ( Input_Line_Length ) := extended_space ;
  4848.       -- prepare input line for reading
  4849.       Next_Position_To_Work := 2 ; -- because col 1 has a dot
  4850.       -- prepare default parameter values
  4851.       -- command is set no matter what
  4852.       -- user_command_number is only valid if the command turns into
  4853.       --                     a user command.  And then, it is set correctly
  4854.       --                     somewhere else
  4855.       numeric_contents := no_numeric_contents ;
  4856.       -- numeric_value is only valid if numeric_contents is changed, and
  4857.       --                     then whichever routine changes it changes
  4858.       --                     the value too...
  4859.       modifier_one     := no_modifier         ;
  4860.       modifier_two     := no_modifier         ;
  4861.       set_length ( text_parameters , 0 ) ;
  4862.       -- 
  4863.       -- OK.  we are ready to parse the line....
  4864.       -- First...get the command string.
  4865.       get_command ; -- get command gets in the string of characters starting
  4866.                     -- at column 2.  It reads until the next character avail
  4867.                     -- is a space.  It stops there and then changes the
  4868.                     -- command string into a real name...
  4869.       -- here, we might have commands which must have their info moved over
  4870.       -- into text paramters only...
  4871.       case command is
  4872.         when if_command         => return ;
  4873.         when write_command 
  4874.            | read_command
  4875.            | insert_command
  4876.            | indexfile_command
  4877.            | index_command      => if next_position_to_work 
  4878.                                             <= input_line_length then
  4879.                                      work_unquoted_text_string ;
  4880.                                      return ;
  4881.                                    end if ;
  4882.         when others             => null ; -- continue the parse...
  4883.       end case ;
  4884.       -- now, get all modifiers and parameters
  4885.       loop
  4886.         skip_blanks ;
  4887.       exit when Next_Position_To_Work >= input_line_length ;
  4888.         -- there is something there 
  4889.         this_char := map_up ( Input_Line ( Next_Position_To_Work ) ) ;
  4890.         if this_char > 128 then
  4891.           cc := ascii.del ;
  4892.         else
  4893.           cc := character'val ( this_char ) ;
  4894.         end if ;
  4895.         case cc is
  4896.           when '+'    => work_numeric_part ( positive_rel_numeric ) ;
  4897.           when '-'    => work_numeric_part ( negative_rel_numeric ) ;
  4898.           -- we have a relative command
  4899.           when '0' | '1' | '2' 
  4900.              | '3' | '4' | '5'
  4901.              | '6' | '7' | '8'
  4902.              | '9'    => work_numeric_part ( absolute_numeric ) ;
  4903.           when ''' | '"' => work_text_string ;
  4904.           when others      => if this_char >= extended_uc_a 
  4905.                               and then this_char <= extended_uc_z then
  4906.                                 work_modifier ;
  4907.                               else
  4908.                                 work_unquoted_text_string ;
  4909.                               end if ;
  4910.         end case ;
  4911.       end loop ;
  4912.     end Parse_Input_Command_Line ;
  4913.      
  4914.     function select_font( New_Font_Number : in Font_Number ) return boolean is
  4915.       font_num        : font_io.positive_count ;
  4916.     begin -- select_font
  4917.       if new_font_number = current_font.number then
  4918.         space_width    := current_font.width ( extended_space ) ;
  4919.         current_font.font_width := space_width ;
  4920.         half_space_width := space_width / 2 ;
  4921.         return true ; -- already set...
  4922.       elsif new_font_number = permanent_font.number then
  4923.         current_font := permanent_font ;
  4924.         space_width    := current_font.width ( extended_space ) ;
  4925.         current_font.font_width := space_width ;
  4926.         half_space_width := space_width / 2 ;
  4927.         return true ;
  4928.       elsif new_font_number = temporary_font.number then
  4929.         current_font := temporary_font ;
  4930.         space_width    := current_font.width ( extended_space ) ;
  4931.         current_font.font_width := space_width ;
  4932.         half_space_width := space_width / 2 ;
  4933.         return true ;
  4934.       else
  4935.         -- must actually read in from disk....
  4936.         -- sets selected font as current font....
  4937.         font_num := font_io.positive_count ( new_font_number ) ;
  4938.         Font_IO.Read  ( font_input_file , current_font , font_num ) ;
  4939.         space_width    := current_font.width ( extended_space ) ;
  4940.         current_font.font_width := space_width ;
  4941.         half_space_width := space_width / 2 ;
  4942.         return true ;
  4943.       end if ;
  4944.     exception
  4945.       when others => return false ;
  4946.     end select_font ;
  4947.      
  4948.     procedure set_fixed_font ( Pitch : Horizontal_Measurement ) is
  4949.     begin -- set_fixed_font
  4950.       current_font.name  := "Mono Pitch               " ;
  4951.       current_font.number:= 0                           ;
  4952.       current_font.vertical_points_per_inch   := 48     ;
  4953.       current_font.horizontal_points_per_inch := 120    ;
  4954.       current_font.Font_width := Pitch ;
  4955.       current_font.Font_height := 8 ;
  4956.       current_font.mappings_necessary := false          ;
  4957.       for posn in extended_character loop
  4958.         current_font.width           (posn)   := horizontal_measurement(pitch);
  4959.         current_font.hammer_intensity(posn)   :=  1 ;
  4960.         current_font.map_string      (posn) (1) := posn ;
  4961.         for inside in 2 .. a_map_string'last loop
  4962.           current_font.map_string    (posn) (inside) := 0    ;
  4963.         end loop ;
  4964.       end loop ;
  4965.       Space_Width         := current_font.width ( extended_space ) ;
  4966.       Half_Space_Width    := Space_Width / 2 ;
  4967.     end set_fixed_font ;
  4968.    
  4969.     procedure printer_misc_global_initialize is
  4970.       pfont_file      : pstring           ;
  4971.       success         : boolean           ;
  4972.        
  4973.       function no_blanks ( s : in pstring ) return string is
  4974.         ot_string : string ( 1 .. length(s) ) ;
  4975.         ot_length : integer ;
  4976.       begin -- no_blanks 
  4977.         ot_length := 0 ;
  4978.         for place in 1 .. length(s) loop
  4979.           if s.data(place) /= ' ' then
  4980.             ot_length := ot_length + 1 ;
  4981.             ot_string(ot_length) := s.data(place);
  4982.           end if ;
  4983.         end loop ;
  4984.         return ot_string( 1 .. ot_length ) ;
  4985.       end no_blanks ;
  4986.      
  4987.       function font_file_exists ( file_name : in pstring ) return boolean is
  4988.         -- look for this file name with no changes
  4989.         temp_file : font_io.file_type ;
  4990.       begin -- font_file_exists
  4991.         font_io.open(temp_file , font_io.in_file , no_blanks(file_name) );
  4992.         font_io.close(temp_file) ;
  4993.         return true ;
  4994.       exception 
  4995.         when io_exceptions.name_error 
  4996.            | io_exceptions.use_error   => return false ;
  4997.         when others                    => return false ;
  4998.       end font_file_exists ;
  4999.         
  5000.       function user_name ( s : in pstring ) return pstring is
  5001.         -- turn this file name into a user name 
  5002.       begin -- user_name 
  5003.         if basic_io_system.directory_separator = ' ' then
  5004.           -- nothing defined
  5005.           return s;
  5006.         else
  5007.           -- ok. we have a basic_io_system.directory separator to look for
  5008.           if position( basic_io_system.directory_separator , s ) /= 0 then
  5009.             -- they defined the basic_io_system.directory, so don't do anything
  5010.             return s;
  5011.           else
  5012.             -- ok, turn it into the appropriate one
  5013.             return basic_io_system.user_directory & s ;
  5014.           end if ;
  5015.         end if ;
  5016.       end user_name ;
  5017.        
  5018.       function wp_name ( s : in pstring ) return pstring is
  5019.         -- turn this file name into a wp name 
  5020.       begin -- wp_name 
  5021.         if basic_io_system.directory_separator = ' ' then
  5022.           -- nothing defined
  5023.           return s;
  5024.         else
  5025.           -- ok. we have a directory separator to look for
  5026.           if position( basic_io_system.directory_separator , s ) /= 0 then
  5027.             -- they defined the directory, so don't do anything
  5028.             return s;
  5029.           else
  5030.             -- ok, turn it into the appropriate one
  5031.             return basic_io_system.word_processor_directory & s ;
  5032.           end if ;
  5033.         end if ;
  5034.       end wp_name ;
  5035.      
  5036.       procedure font_to_read   ( orig_file_name  : in  pstring   ;
  5037.                                 final_file_name : out pstring   ;
  5038.                                 fin_successfull : out boolean ) is
  5039.         -- For Editor Program Files (such as help)
  5040.         -- look for the orig_file_name on the appropriate disks.  Return
  5041.         -- successfull if found, and also set the final_file_name as 
  5042.         -- the fully elaborated file path/name
  5043.         new_name : pstring ;
  5044.         successfull : boolean ;
  5045.       begin -- font_to_read
  5046.         if font_file_exists ( orig_file_name ) then
  5047.           final_file_name := orig_file_name ;
  5048.           successfull     := true ;
  5049.         else
  5050.           -- check for a user directory 
  5051.           new_name := user_name( orig_file_name ) ;
  5052.           if new_name = orig_file_name then
  5053.             -- nothing we can do about it
  5054.             final_file_name := blank_line ;
  5055.             successfull     := false      ;
  5056.           else
  5057.             if font_file_exists( new_name ) then
  5058.               final_file_name := new_name ;
  5059.               successfull     := true     ;
  5060.             else
  5061.               final_file_name := blank_line ;
  5062.               successfull     := false      ;
  5063.             end if ;
  5064.           end if ;
  5065.           -- just finished looking in the user directory
  5066.           if not successfull then
  5067.             -- look in the system directory 
  5068.             new_name := wp_name( orig_file_name ) ;
  5069.             if new_name = orig_file_name then
  5070.               -- nothing we can do about it
  5071.               final_file_name := blank_line ;
  5072.               successfull     := false      ;
  5073.             else
  5074.               if font_file_exists( new_name ) then
  5075.                 final_file_name := new_name ;
  5076.                 successfull     := true     ;
  5077.               else
  5078.                 final_file_name := blank_line ;
  5079.                 successfull     := false      ;
  5080.               end if ;
  5081.             end if ;
  5082.           end if ;
  5083.         end if ;
  5084.         fin_successfull := successfull ;
  5085.       end font_to_read ;
  5086.          
  5087.       function e ( c : character ) return extended_character is
  5088.       begin -- e
  5089.         return extended_character( character'pos( c ) ) ;
  5090.       end e ;
  5091.        
  5092.     begin -- printer_misc_global_initialize
  5093.       font_to_read( string_to_pstring ( font_file ) , pfont_file , success ) ;
  5094.       -- We have font_file_exists & Others because Telesoft Ada
  5095.       -- messes with file if we use SOK_TO_READ to determine its location
  5096.       -- ( text_io Stuff in WPGLOBAL )
  5097.       if not success then
  5098.         error( " Font File Not Available." , fatal_error ,
  5099.                              operator_wait , short_beep ) ;
  5100.       end if ;
  5101.       font_io.open  ( font_input_file , font_io.in_file ,
  5102.                                         no_blanks ( pfont_file ) ) ;
  5103.       -- Now, we have some character processing information
  5104.       Default_Characters_Array := (
  5105.                            e( ascii.nul ),       -- Subscript_Start    ,
  5106.                            e( ascii.nul ),       -- Subscript_Stop     ,
  5107.                            e( '~'       ),       -- Subscript_Toggle   ,
  5108.                            e( ascii.nul ),       -- Superscript_Start  ,
  5109.                            e( ascii.nul ),       -- Superscript_Stop   ,
  5110.                            e( '^'       ),       -- Superscript_Toggle ,
  5111.   e( ascii.nul ),       -- e( '<'       ),       -- Underline_Start    ,
  5112.   e( ascii.nul ),       -- e( '>'       ),       -- Underline_Stop     ,
  5113.                            e( ascii.nul ),       -- Underline_Toggle   ,
  5114.                            e( ascii.nul ),       -- UCont_Start        ,
  5115.                            e( ascii.nul ),       -- UCont_Stop         ,
  5116.   e( ascii.nul ),       -- e( '|'       ),       -- UCont_Toggle       ,
  5117.                            e( ascii.nul ),       -- UFoot_Start        ,
  5118.                            e( ascii.nul ),       -- UFoot_Stop         ,
  5119.                            e( ascii.nul ),       -- UFoot_Toggle       ,
  5120.   e( ascii.nul ),       -- e( '{'       ),       -- Bold_Start         ,
  5121.   e( ascii.nul ),       -- e( '}'       ),       -- Bold_Stop          ,
  5122.                            e( ascii.nul ),       -- Bold_Toggle        ,
  5123.   e( ascii.nul ),       -- e( '['       ),       -- Shadow_Start       ,
  5124.   e( ascii.nul ),       -- e( ']'       ),       -- Shadow_Stop        ,
  5125.                            e( ascii.nul ),       -- Shadow_Toggle      ,
  5126.                            e( ascii.nul ),       -- Temp_Font_Start    ,
  5127.                            e( ascii.nul ),       -- Temp_Font_Stop     ,
  5128.   e( ascii.nul ),       -- e( '/'       ),       -- Temp_Font_Toggle   ,
  5129.                            e( ascii.nul ),       -- Soft_Hyphen        ,
  5130.                            e( '\'       ),       -- Dot_Leader         ,
  5131.                            e( ascii.nul ),       -- Character_Tab      ,
  5132.                            e( ' '       ),       -- Actual_Space       ,
  5133.   e( ascii.nul ),       -- e( '_'       ),       -- Forced_Space       ,
  5134.                            e( ascii.nul ),       -- Text_Character     ,
  5135.                            e( ascii.nul )        -- Illegal_Character  ,
  5136.                                         ) ; 
  5137.       -- End of character processing information
  5138.     -- exception
  5139.       -- when others => -- Here on font file error
  5140.             -- error( " Font File Not Available." , fatal_error ,
  5141.                              -- operator_wait , short_beep ) ;
  5142.     end printer_misc_global_initialize ;
  5143.      
  5144.     procedure initialize_printer_misc_for_a_new_document     is
  5145.     begin -- initialize_printer_misc_for_a_new_document
  5146.       end_of_main_input_file    := false ;
  5147.       ready_to_stop             := false ;
  5148.       processing_comment_area   := false ;
  5149.       amount_waiting_to_move_vertically_before_line := 0  ;
  5150.       amount_waiting_to_move_vertically_after_line  := 0  ;
  5151.       kind_of_move_before_line  := move_forward_on_page ;
  5152.       kind_of_move_after_line   := move_forward_on_page ;
  5153.       text_waiting_inside_filled_paragraph := false ;
  5154.       just_did_tab_command      := false ;
  5155.       for numb in 1 .. max_switches loop 
  5156.         switches ( numb ) := false ;
  5157.       end loop ;
  5158.       index_file_is_open := false ;
  5159.       for numb in 1 .. max_user_variables loop 
  5160.         set_length ( user_variable_data ( numb ) , 0 ) ;
  5161.       end loop ;
  5162.       specifically_requested_to_remain_on_this_line := false ;
  5163.       index_file_name := no_file ;
  5164.     end initialize_printer_misc_for_a_new_document ;
  5165.    
  5166.     procedure finish_printer_misc_for_an_old_document     is
  5167.     begin -- finish_printer_misc_for_an_old_document
  5168.       null ;
  5169.     end finish_printer_misc_for_an_old_document ;
  5170.    
  5171.     procedure close_printer_misc is
  5172.     begin -- close_printer_misc
  5173.       Font_IO.close ( font_input_file ) ;
  5174.     end close_printer_misc ;
  5175.      
  5176.   begin -- Printer_Misc 
  5177.     printer_misc_global_initialize ;
  5178.   end Printer_Misc ;
  5179.    
  5180.   --$$$- PRNTMSC
  5181.  
  5182. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5183. --prntcmd
  5184. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5185.  
  5186.   --$$$+ PRNTCMD 
  5187.     
  5188.   --
  5189.   -- File 0xx
  5190.   --
  5191.   -- Formatter Written By Robert S. Cymbalski
  5192.   --                      Science Applications International Corporation
  5193.   --
  5194.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  5195.   --
  5196.    
  5197.   with text_io         ;
  5198.    
  5199.   with string_library  ;
  5200.   use  string_library  ;
  5201.     
  5202.   with basic_io_system ;
  5203.    
  5204.   with crt_windows     ;
  5205.   use  crt_windows     ;
  5206.     
  5207.   with Wordp_Globals   ;
  5208.   use  Wordp_Globals   ;
  5209.    
  5210.   with name_tree ;
  5211.   use  name_tree ;
  5212.    
  5213.   with Printer_globals ;
  5214.   use  printer_globals ;
  5215.    
  5216.   with printf    ;
  5217.   use  printf    ;
  5218.    
  5219.   with print_in_to_out ;
  5220.   use  print_in_to_out ;
  5221.    
  5222.   with print_out ;
  5223.   use  print_out ;
  5224.    
  5225.   with printer_misc ;
  5226.   use  printer_misc ;
  5227.    
  5228.   Package Printer_Commands is
  5229.      
  5230.     Procedure Options ( Return_Input_Line_Contains_Text : out boolean ) ;
  5231.     
  5232.     procedure initialize_printer_commands_for_a_new_document  ;
  5233.      
  5234.     procedure finish_printer_commands_for_an_old_document     ;
  5235.    
  5236.     procedure close_printer_commands ;
  5237.      
  5238.     procedure force_into_input_stream ( s : pstring ;
  5239.                                       Input_Line_Contains_Text : out boolean) ;
  5240.    
  5241.     procedure load_input_line ( skip_blank_lines : boolean := false ) ;
  5242.    
  5243.     Procedure Move_Before_Current_Line ( allow_one_extra : boolean := false ;
  5244.                                          allow_one_less  : boolean := false ) ;
  5245.    
  5246.     procedure tidy_up_and_output_filled_line 
  5247.                                 ( Last_Line_In_Paragraph : Boolean := False ) ;
  5248.    
  5249.     Filling_output_line : output_line_pointer ;
  5250.         -- this is where the filled text goes...
  5251.      
  5252.     filling_trailing_spaces : integer         ;
  5253.      
  5254.   end Printer_Commands ;
  5255.    
  5256.   Package Body Printer_Commands is
  5257.    
  5258.     -- package cmd_io is new enumeration_io(text_formatter_command) ;
  5259.      
  5260.     Temp_Input_Pstring : Pstring ;
  5261.      
  5262.     Vertical_Page_Limit : Integer ;
  5263.       -- It is really, normally, a Vertical_Measurement, but if we have a
  5264.       -- lot of foot notes, we could make it negative, meaning that we have
  5265.       -- suddenly generated over a page of foot notes....
  5266.       -- what is the last position we can use vertically??
  5267.          
  5268.     erased_it : boolean := false ;
  5269.     last_line : integer :=     0 ;
  5270.      
  5271.     procedure deb ( s : string ; info : integer := 0 ) is
  5272.     begin -- deb
  5273.       if ( s = "PAUSE" ) or ( s = "pause" ) then
  5274.         -- we must pause ...
  5275.         if User_Pause ( "Pause!" , true ) then
  5276.           raise users_requested_abort ;
  5277.         end if ;
  5278.         erased_it := true ;
  5279.         clear_window( master_window ) ;
  5280.         clear_prompt( master_window ) ;
  5281.         last_line  := 1 ;
  5282.       else
  5283.         if not erased_it then
  5284.           erased_it := true ;
  5285.           clear_window( master_window ) ;
  5286.           clear_prompt( master_window ) ;
  5287.           last_line  := 1 ;
  5288.         elsif ( last_line = 20 ) then
  5289.           -- we must pause ...
  5290.           if User_Pause ( "Pause!" , true ) then
  5291.             raise users_requested_abort ;
  5292.           end if ;
  5293.           erased_it := false ;
  5294.         end if ;
  5295.         -- here ready to go to work
  5296.         last_line := last_line + 1 ;
  5297.         goto_line_column ( master_window , last_line , 2 ) ;
  5298.         put ( s ) ;
  5299.         if s'length < 30 then
  5300.           for posn in s'length + 1 .. 30 loop
  5301.             put ( ' ' ) ;
  5302.           end loop ;
  5303.         end if ;
  5304.         put ( "  " ) ;
  5305.         put ( info , 5 ) ;
  5306.       end if ;
  5307.     end deb ;
  5308.      
  5309.     procedure reset_vertical_physical_page_limits is
  5310.       -- physical boundries were changed....re set any other information
  5311.       -- note that this MUST be called after each page is output, just in
  5312.       -- case footnotes change things....
  5313.       page_number_line_ready  : boolean              ;
  5314.       bottom_Loc              : Integer              ;
  5315.       PageNum_Loc             : Integer              ;
  5316.       Footer_Loc              : Integer              ;
  5317.       FootNote_And_Footer_Loc : Integer              ;
  5318.       -- These items are really vertical_measurements, but we want to
  5319.       -- do our own error handling in case the user asked for 
  5320.       -- strange things....
  5321.       we_have_command_error   : Boolean := false     ;
  5322.       err_code                : Integer              ;
  5323.     begin -- reset_vertical_physical_page_limits
  5324.       -- First: We must move to the correct vertical position....
  5325.       -- page number ?
  5326.       page_number_line_ready := Current_Document_Parameters.Page_Numbering_On 
  5327.                         and not Current_Document_Parameters.Number_Page_At_Top ;
  5328.       --  Bottom_Loc is the last printable vertical position
  5329.       Bottom_Loc  := Current_Physical_Parameters.Paper_Length
  5330.                       - Current_Physical_Parameters.Bottom_Margin ;
  5331.                       --###-- RSC -- work with font_height later!!!
  5332.       If Bottom_Loc < 0 then
  5333.         -- If bottom margin is > paper_length, we ZERO Bottom Margin
  5334.         Current_Physical_Parameters.Bottom_Margin := 0 ;
  5335.         Bottom_Loc := Current_Physical_Parameters.Paper_Length ;
  5336.         we_have_command_error := true ;
  5337.         err_code      := 1    ;
  5338.       end if ;
  5339.       -- Footer_Loc is where to start the footer
  5340.       --      Note that the page number shares the last line with the
  5341.       --      footer
  5342.       If Current_Document_Parameters.Footing_Height > 0 then
  5343.         -- page numbers do not matter
  5344.         Footer_Loc  := Bottom_Loc - Current_Document_Parameters.Footing_Height ;
  5345.       elsif page_number_line_ready then
  5346.         -- footers do not matter
  5347.         Footer_Loc  := Bottom_Loc - current_vertical_motion_index 
  5348.                                   - current_vertical_motion_index ;
  5349.                                       -- page number takes two lines..
  5350.                                       -- or ?? - Current_Font.Font_Height ;
  5351.       else
  5352.         Footer_Loc  := Bottom_Loc ;
  5353.       end if ;
  5354.       -- JENNIFER ! Read This !
  5355.       If Footer_Loc < 0 then
  5356.         we_have_command_error := true ;
  5357.         Footer_Loc := Bottom_Loc ;
  5358.         If Current_Document_Parameters.Footing_Height > 0 then
  5359.           -- Footing Too Large...
  5360.           err_code := 2 ;
  5361.           Current_Document_Parameters.Footing_Height := 0 ;
  5362.         else
  5363.           -- page number problem 
  5364.           err_code := 3 ;
  5365.           Current_Document_Parameters.Page_Numbering_On := false ;
  5366.         end if ;
  5367.       end if ;
  5368.       -- FootNote_And_Footer_Loc is location to start the footer information
  5369.       FootNote_And_Footer_Loc  := Footer_Loc
  5370.                       - Current_Document_Parameters.FootNote_Height ;
  5371.       Vertical_Page_Limit := Footnote_And_Footer_Loc ;
  5372.       if we_have_command_error then
  5373.         case err_code is
  5374.           when 1 => command_error
  5375.                      ("Bottom Margin larger than Paper Length. Margin Zeroed."
  5376.                      , true );
  5377.           when 2 => command_error
  5378.                      ( "Paper not long enough for Footer.  Footing Zeroed."
  5379.                      , true ) ;
  5380.           when 3 => command_error
  5381.                      ( "Paper not long enough for page number.  Turned Off."
  5382.                      , true );
  5383.           when others => null ; -- can't get here
  5384.         end case ;
  5385.       end if ;
  5386.     end reset_vertical_physical_page_limits ;
  5387.    
  5388.     Procedure Move_Before_Current_Line ( allow_one_extra : boolean := false ;
  5389.                                          allow_one_less  : boolean := false ) is
  5390.       -- perform any necessary movement required before the current line
  5391.       -- allow one extra if this is the last line of a paragraph
  5392.       -- allow one less if this is the first line of a paragraph which
  5393.       -- has more lines following.
  5394.       The_Vertical_Page_Limit : Vertical_Measurement := Vertical_Page_Limit ;
  5395.     begin -- move_before_current_line
  5396.       if need_to_start_page then
  5397.         start_a_page ;
  5398.       end if ;
  5399.       case kind_of_move_before_line is
  5400.         when stay_on_this_line           => null ; -- don't do anything
  5401.         when move_forward_on_page        => 
  5402.                     if amount_waiting_to_move_vertically_before_line > 0 then
  5403.                       -- we must do the movement...
  5404.                       if allow_one_less then
  5405.                         The_Vertical_Page_Limit := The_Vertical_Page_Limit
  5406.                                 - current_vertical_motion_index ;
  5407.                       elsif allow_one_extra then
  5408.                         The_Vertical_Page_Limit := The_Vertical_Page_Limit
  5409.                                 + current_vertical_motion_index ;
  5410.                       end if ;
  5411.                       if printer_vertical_position 
  5412.                            + amount_waiting_to_move_vertically_before_line 
  5413.                                >=  The_Vertical_Page_Limit then
  5414.                         -- new page...
  5415.                         end_a_page ;
  5416.                         reset_vertical_physical_page_limits ;
  5417.                         start_a_page ;
  5418.                         -- kind_of_move_after_line                      :=
  5419.                                 -- stay_on_this_line ;
  5420.                         -- amount_waiting_to_move_vertically_after_line :=
  5421.                                 -- 0                 ;
  5422.                         -- no need to move because we have just started a
  5423.                         -- new page
  5424.                       else
  5425.                         -- must do it...
  5426.                         move_down_vertically ( 
  5427.                             amount_waiting_to_move_vertically_before_line ) ;
  5428.                       end if ;
  5429.                     end if ;
  5430.         when move_backward_on_page       =>
  5431.                     if amount_waiting_to_move_vertically_before_line > 0 
  5432.                       -- we must do the movement...
  5433.                     and then printer_vertical_position 
  5434.                            - amount_waiting_to_move_vertically_before_line
  5435.                                >= 0 then
  5436.                         -- we can move...
  5437.                       move_to_vertical_position ( printer_vertical_position -
  5438.                           amount_waiting_to_move_vertically_before_line ) ;
  5439.                     end if ;
  5440.         when move_to_absolute_position   =>
  5441.                       move_to_vertical_position ( 
  5442.                           amount_waiting_to_move_vertically_before_line ) ;
  5443.       end case ;
  5444.       kind_of_move_before_line                      := 
  5445.                               kind_of_move_after_line                      ;
  5446.       amount_waiting_to_move_vertically_before_line := 
  5447.                               amount_waiting_to_move_vertically_after_line ;
  5448.       -- if we are waiting on some motion....do the movement...
  5449.       -- 1st: determine how much room is left on page...
  5450.       -- 2nd: add one line of room if requested
  5451.       -- 3rd: if end of page then put in bottom information
  5452.       -- 4th:   & then if double column move to top of second col
  5453.       --                                and then set new horizontal
  5454.       -- if real_center_right > 0 then  -- we have two columns
  5455.       -- 5th:   & then if not double column start a new page
  5456.       -- 6th: else if not eop then simply put in any requested lines
  5457.       --         set any necessary horizontal bounds before we process a line
  5458.       --         which will be output...
  5459.     end move_before_current_line ;
  5460.      
  5461.     procedure finish_current_text( vert_request : vertical_movement_request_type
  5462.                                                         := move_forward_on_page;
  5463.                                     vert_number  : integer := 0           ) is
  5464.       -- we have a request to change an option which will have far reaching
  5465.       -- effects.  Therefore, finish any output which might be pending
  5466.       -- then, the vert request should be processed...
  5467.       -- allow_abort : boolean ;
  5468.     begin -- finish_current_text
  5469.       if ( vert_request = move_forward_on_page ) 
  5470.       and then ( vert_number = 0 )
  5471.       and then ( not text_waiting_inside_filled_paragraph ) then
  5472.         -- we don't need to do a thing...
  5473.         return ;
  5474.       end if ;
  5475.       -- First do any saved up vertical movement 
  5476.       kind_of_move_after_line                      := vert_request ;
  5477.       amount_waiting_to_move_vertically_after_line := vert_number
  5478.                            * Current_Vertical_Motion_Index ;
  5479.       if text_waiting_inside_filled_paragraph then
  5480.         amount_waiting_to_move_vertically_after_line := 
  5481.                     amount_waiting_to_move_vertically_after_line 
  5482.                     + Current_Vertical_Motion_Index ;
  5483.         -- because we put in one <lf> no matter what.....
  5484.       end if ;
  5485.       move_before_current_line ( text_waiting_inside_filled_paragraph ) ;
  5486.                 -- does movement and allows this last line of paragraph on
  5487.                 -- page if filling is on...
  5488.                 -- moves after settings to before settings.
  5489.       if text_waiting_inside_filled_paragraph then
  5490.         -- we need to finish the current paragraph....
  5491.         tidy_up_and_output_filled_line ( true ) ;
  5492.         -- that's it, when we try to merge a new line and don't find any 
  5493.         -- text, then we will set correctly for a new paragraph...
  5494.       end if ;
  5495.     end finish_current_text ;
  5496.    
  5497.     procedure reset_horizontal_physical_page_limits is
  5498.       -- physical boundries were changed....re set any other information
  5499.     begin -- reset_horizontal_physical_page_limits
  5500.       -- note that this must check to make sure that we have some room
  5501.       -- between the margins for text
  5502.       rightmost_text_position     := current_physical_parameters.paper_width
  5503.                            - current_physical_parameters.right_margin
  5504.                            - current_formatting_parameters.Right_Indentation   ;
  5505.       leftmost_edge_position      := current_physical_parameters.left_margin   ;
  5506.       leftmost_normal_position    := leftmost_edge_position
  5507.                            + current_formatting_parameters.Left_Indentation    ;
  5508.       leftmost_para_text_position := leftmost_normal_position 
  5509.                            + current_formatting_parameters.Paragraph_Indent    ;
  5510.       leftmost_text_position      := leftmost_normal_position
  5511.                            + current_formatting_parameters.Subsequent_Line_Ind ;
  5512.     end reset_horizontal_physical_page_limits ;
  5513.      
  5514.     procedure horizontal_control_values_changed is
  5515.       -- physical boundries were changed....re set any other information
  5516.     begin -- horizontal_control_values_changed
  5517.       reset_horizontal_physical_page_limits ;
  5518.     end horizontal_control_values_changed ;
  5519.    
  5520.   Function New_Value ( old_value : integer ;
  5521.                        smallest  : integer ;
  5522.                        largest   : integer ;
  5523.                        factor    : integer ) return integer is
  5524.     -- old_value is in real units
  5525.     -- smallest and largest are in user's entered units
  5526.     -- factor tells how to convert old_value to user's units, and
  5527.     -- then how to turn the resulting number into an internal number
  5528.     new_val : integer ;
  5529.     old_val : integer ;
  5530.   begin  -- new_value
  5531.     -- we get here knowing that we have some type of numeric contents
  5532.     if modifier_one = default_modifier then
  5533.       -- we simply set the default value....
  5534.       new_val := user_command_number ;
  5535.     elsif modifier_one =  on_modifier then
  5536.       new_val := largest ;
  5537.     elsif modifier_one = off_modifier then
  5538.       new_val := 0 ;
  5539.     elsif numeric_contents = absolute_numeric then
  5540.       -- we must determine the new value ....
  5541.       new_val := numeric_value ;
  5542.     elsif numeric_contents = positive_rel_numeric then
  5543.       old_val := old_value / factor ;
  5544.       -- to change into user units...
  5545.       if largest - old_val < numeric_value then
  5546.         -- old_val + numeric_value > largest
  5547.         command_error (
  5548.             "Relative Numeric Parameter Results In Invalid Number." , true );
  5549.       else
  5550.         new_val := old_val + numeric_value ;
  5551.       end if ;
  5552.     elsif numeric_contents = negative_rel_numeric then
  5553.       -- negative
  5554.       old_val := old_value / factor ;
  5555.       -- to change into user units...
  5556.       if numeric_value > old_val - smallest then
  5557.         -- old_val - numeric_value < smallest
  5558.         command_error (
  5559.             "Relative Numeric Parameter Results In Invalid Number." , true );
  5560.       else
  5561.         new_val := old_val - numeric_value ;
  5562.       end if ;
  5563.     else
  5564.       -- no modifier or numeric....defaults to zero
  5565.       new_val := 0 ; -- for such commands as ".add" meaning ".add 0" or ".newp"
  5566.     end if ;
  5567.     -- we get here with new_val as the new value to use...
  5568.     if new_val > largest then
  5569.       -- number
  5570.       command_error ("Numeric Parameter Is Too Large." , true );
  5571.     elsif new_val < smallest then
  5572.       command_error ("Numeric Parameter Is Too Small." , true );
  5573.     else
  5574.       return new_val * factor ;
  5575.     end if ;
  5576.   exception
  5577.     when numeric_error => command_error (
  5578.                        "Numeric Parameter Results In Invalid Number." , true ) ;
  5579.   end new_value ;
  5580.      
  5581.   procedure load_input_line ( skip_blank_lines : boolean := false ) is
  5582.     eof : boolean ;
  5583.   begin -- load_input_line
  5584.     loop
  5585.       read_next_line ( temp_input_pstring , eof ) ;
  5586.     exit when length ( temp_input_pstring ) > 0 
  5587.     or else ( not skip_blank_lines ) 
  5588.     or else eof ;
  5589.     end loop ;
  5590.     physical_input_lines := physical_input_lines + 1 ;
  5591.     -- convert to input line...
  5592.     input_line_length := length ( temp_input_pstring ) ;
  5593.     for posn in 1 .. input_line_length loop
  5594.       input_line ( posn ) := extended_character ( 
  5595.                           character'pos ( temp_input_pstring.data ( posn ) ) ) ;
  5596.     end loop ;
  5597.     if input_line_length < max_line_length then
  5598.       input_line ( input_line_length + 1 ) := extended_space ;
  5599.     end if ;
  5600.     if eof then
  5601.       if where_to_read = alternate_input_file then
  5602.         if length ( temp_input_pstring ) = 0 then
  5603.           -- end of a secondary file
  5604.           select_for_read ( main_input_file ) ;
  5605.           load_input_line ( skip_blank_lines ) ;
  5606.         -- else work this line as is before returning to main file
  5607.         end if ;
  5608.       else
  5609.         if length ( temp_input_pstring ) = 0 then
  5610.           end_of_main_input_file := true ;
  5611.         -- else work this line as is before returning to main file
  5612.         end if ;
  5613.       end if ;
  5614.     end if ;
  5615.     -- -- here is where the soft hyphen recovery would go
  5616.     -- innxt := 1 ;
  5617.     -- if ( length(instring) > 3 ) then  
  5618.       -- -- this is the soft hyphen recover routine
  5619.       -- for w in reverse length(in_string)-2 .. length(in_string) loop
  5620.         -- if in_string.data(w) = soft_hyphen then
  5621.           -- if filling then
  5622.             -- in_string.data(w) := character'val(1) ; 
  5623.             -- -- because filling will bring in next line
  5624.           -- else
  5625.             -- in_string.data(w) := '-' ;
  5626.           -- end if ;
  5627.           -- set_length(in_string , w) ;
  5628.         -- end if ;
  5629.       -- end loop ;
  5630.     -- end if ;
  5631.   end load_input_line ;
  5632.    
  5633.   procedure force_into_input_stream ( s : pstring ;
  5634.                                       Input_Line_Contains_Text : out boolean) is
  5635.   begin -- force_into_input_stream
  5636.     for posn in 1 .. length ( s ) loop
  5637.       input_line(posn) :=extended_character ( character'pos ( s.data(posn) ) ) ;
  5638.     end loop ;
  5639.     Input_Line_Length := length ( s ) ;
  5640.     Input_Line_Contains_Text := Input_Line_Length > 0 ;
  5641.   end force_into_input_stream ;
  5642.      
  5643.   procedure param_error ( op : an_allowed_option ) is
  5644.     -- error.  They have put the op in a command which does not
  5645.     -- allow that option
  5646.     temp_string : string ( 1 .. 21 ) ;
  5647.   begin -- param_error
  5648.     case op is
  5649.       when o_any_numeric => temp_string := "Numeric              " ;
  5650.       when o_abs_numeric => temp_string := "Absolute Numeric     " ;
  5651.       when o_rel_numeric => temp_string := "Relative Numeric     " ;
  5652.       when o_on_off      => temp_string := "On                   " ;
  5653.       when o_off         => temp_string := "Off                  " ;
  5654.       when o_toggle      => temp_string := "Toggle               " ;
  5655.       when o_top_bottom  => temp_string := "Top and Bottom       " ;
  5656.       when o_l_r_c_alt   => temp_string := "Left/Right/Center/Alt" ; 
  5657.       when o_text_param  => temp_string := "String               " ;
  5658.       when o_none        => null ; -- cannot get here anyway
  5659.     end case ;
  5660.     command_error ( ps_to_s ( compress( temp_string ) 
  5661.                             & " Parameters not allowed with this command." ) 
  5662.                             , true );
  5663.   end param_error ;
  5664.    
  5665.   procedure allow_options ( exactly_one_allowed : boolean ;
  5666.                             op_1 , op_2 , op_3 , op_4 ,
  5667.                             op_5 , op_6 , op_7 , op_8 : an_allowed_option 
  5668.                                                           := o_none ) is
  5669.     -- examine the current options to determine if any have been set
  5670.     -- which are not allowed for this command
  5671.     cur_allowed : array ( an_allowed_option ) of boolean 
  5672.                        := ( an_allowed_option'first .. an_allowed_option'last
  5673.                              => false ) ;
  5674.     op_count : integer := 0 ;
  5675.   begin -- allow_options
  5676.     cur_allowed ( op_1 ) := true ;
  5677.     cur_allowed ( op_2 ) := true ;
  5678.     cur_allowed ( op_3 ) := true ;
  5679.     cur_allowed ( op_4 ) := true ;
  5680.     cur_allowed ( op_5 ) := true ;
  5681.     cur_allowed ( op_6 ) := true ;
  5682.     cur_allowed ( op_7 ) := true ;
  5683.     cur_allowed ( op_8 ) := true ;
  5684.     if numeric_contents /= no_numeric_contents then
  5685.       op_count := op_count + 1 ;
  5686.       if cur_allowed ( o_any_numeric ) then
  5687.         null ; -- we have a numeric and we allow any numeric
  5688.       elsif ( numeric_contents = absolute_numeric ) then
  5689.         if cur_allowed ( o_abs_numeric ) then
  5690.           null ; -- again, we have a good one...
  5691.         else
  5692.           -- error, absolute numeric not allowed for this command
  5693.           param_error ( o_abs_numeric ) ;
  5694.         end if ;
  5695.       elsif cur_allowed ( o_rel_numeric ) then
  5696.         null ; -- good, we have a relative
  5697.       else
  5698.         -- error, we have relative but it is not allowed
  5699.         param_error ( o_rel_numeric ) ;
  5700.       end if ;
  5701.     end if ;
  5702.     if modifier_one     /= no_modifier         then
  5703.       op_count := op_count + 1 ;
  5704.       if modifier_one = on_modifier then
  5705.         if not cur_allowed ( o_on_off      ) then
  5706.           param_error ( o_on_off ) ;
  5707.         end if ;
  5708.       elsif modifier_one = off_modifier then
  5709.         if not ( cur_allowed ( o_on_off ) or cur_allowed ( o_off ) ) then
  5710.           param_error ( o_off ) ;
  5711.         end if ;
  5712.       elsif modifier_one = toggle_modifier then
  5713.         if not cur_allowed ( o_toggle      ) then
  5714.           param_error ( o_toggle ) ;
  5715.         end if ;
  5716.       elsif modifier_one = top_modifier
  5717.       or else modifier_one = bottom_modifier then
  5718.         if not cur_allowed ( o_top_bottom      ) then
  5719.           param_error ( o_top_bottom ) ;
  5720.         end if ;
  5721.       elsif modifier_one = default_modifier then
  5722.         null ; -- it has to be ok...
  5723.       else
  5724.         -- it is left/right/center/alt
  5725.         if not cur_allowed ( o_l_r_c_alt ) then
  5726.           param_error ( o_l_r_c_alt ) ;
  5727.         end if ;
  5728.       end if ;
  5729.       if modifier_two     /= no_modifier         then
  5730.         op_count := op_count + 1 ;
  5731.         if modifier_two = on_modifier then
  5732.           if not cur_allowed ( o_on_off      ) then
  5733.             param_error ( o_on_off ) ;
  5734.           end if ;
  5735.         elsif modifier_two = off_modifier then
  5736.           if not ( cur_allowed ( o_on_off ) or cur_allowed ( o_off ) ) then
  5737.             param_error ( o_off ) ;
  5738.           end if ;
  5739.         elsif modifier_two = toggle_modifier then
  5740.           if not cur_allowed ( o_toggle      ) then
  5741.             param_error ( o_toggle ) ;
  5742.           end if ;
  5743.         elsif modifier_two = top_modifier
  5744.         or else modifier_two = bottom_modifier then
  5745.           if not cur_allowed ( o_top_bottom      ) then
  5746.             param_error ( o_top_bottom ) ;
  5747.           elsif modifier_one = top_modifier 
  5748.           or    modifier_one = bottom_modifier then
  5749.             command_error ("Cannot have multiple vertical parameters." , true );
  5750.           end if ;
  5751.         elsif modifier_two = default_modifier then
  5752.           null ; -- it has to be ok...
  5753.         else
  5754.           -- it is left/right/center/alt
  5755.           if not cur_allowed ( o_l_r_c_alt ) then
  5756.             param_error ( o_l_r_c_alt ) ;
  5757.           elsif modifier_one = left_modifier
  5758.           or    modifier_one = right_modifier
  5759.           or    modifier_one = center_modifier
  5760.           or    modifier_one = alternating_modifier then
  5761.             command_error ("Cannot have multiple horizontal parameters.",true);
  5762.           end if ;
  5763.         end if ;
  5764.       end if ;
  5765.     end if ;
  5766.     if length( text_parameters ) > 0           then
  5767.       op_count := op_count + 1 ;
  5768.       if not cur_allowed ( o_text_param  ) then
  5769.         param_error ( o_text_param ) ;
  5770.       end if ;
  5771.     end if ;
  5772.     if exactly_one_allowed 
  5773.     and then op_count /= 1 then
  5774.       command_error("Exactly One Parameter must be given with this command."
  5775.                         , true );
  5776.     end if ;
  5777.   end allow_options ;
  5778.      
  5779.     procedure initialize_printer_commands_globally is
  5780.      
  5781.     procedure add ( cmd : text_formatter_command ; name : string ;
  5782.                     default : integer ) is
  5783.     begin -- add
  5784.       insert_name ( name , cmd , default , command_tree ) ;
  5785.     end add ;
  5786.          
  5787.     procedure build_command_tree_1 is
  5788.       -- put the information into the tree so that we can get the
  5789.       -- data back later
  5790.       -- e - extra command added to do the same thing as an old command
  5791.       -- c - this command conflicts with old commands.  Old commands will
  5792.       --     need to be spelled out further
  5793.       -- n - new command added
  5794.       -- x - old command changed
  5795.     begin -- build_command_tree_1 
  5796.       -- First, to get the basic tree set up
  5797.       add ( mult_line_spacing_command   , "multiple_line_spacing",000 );
  5798.       add ( fill_command                , "filling"             , 000 ) ;
  5799.       add ( center_command              , "center"              , 000 ) ;
  5800.       add ( shadow_printing_command     , "italic_printing"     , 000 ) ; --e
  5801.       add ( subpara_command             , "subparagraph"        , 000 ) ; --4
  5802.       add ( right_margin_command        , "right_margin_in_tenths",000 ); --e
  5803.       add ( underline_chars_command     , "underline_characters", 000 ) ;
  5804.       -- Now, fill in ...
  5805.       add ( add_command                 , "add_blank_line"      , 000 ) ;
  5806.       add ( bold_command                , "bold"                , 000 ) ; 
  5807.       add ( backward_add_command        , "backward_add"        , 000 ) ; --e
  5808.       add ( backward_add_command        , "badd"                , 000 ) ;
  5809.       add ( binding_command             , "binding_edge"        , 000 ) ;
  5810.       add ( bottom_margin_command       , "bottom_margin_in_sixths",000); --e
  5811.       add ( bottom_margin_command       , "bmargin_in_sixths"   , 000 ) ;
  5812.       -- add ( center_command              , "center"              , 000 ) ;
  5813.       add ( dot_lead_command            , "c_dot_leader"        , 000 ) ; --e
  5814.       add ( char_spacing_command        , "character_spacing"   , 000 ) ;
  5815.       add ( prop_spacing_command        , "change_to_font"      , 000 ) ; --x
  5816.       add ( underline_cont_command      , "continuous_underline", 000 ) ; --e
  5817.       add ( comments_command            , "comments"            , 000 ) ; --x
  5818.       add ( date_dmy_command            , "dmy"                 , 000 ) ;
  5819.       add ( dot_lead_command            , "dlead"               , 000 ) ; 
  5820.       add ( justify_numbers_command     , "dots"                , 000 ) ;
  5821.       add ( end_page_command            , "endpage"             , 000 ) ; --4
  5822.       add ( else_command                , "else"                , 000 ) ;
  5823.       add ( end_page_command            , "end_page"            , 000 ) ; --e5
  5824.       add ( finish_command              , "end_if"              , 000 ) ; --ec
  5825.       add ( envelope_feed_command       , "envelope_feed"       , 000 ) ;
  5826.     end build_command_tree_1 ;
  5827.      
  5828.     procedure build_command_tree_2 is
  5829.     begin -- build_command_tree_2 
  5830.       -- add ( fill_command                , "filling"             , 000 ) ;
  5831.       add ( fancy_print_command         , "fancy_printing"      , 000 ) ;
  5832.       add ( finish_command              , "finish"              , 000 ) ;
  5833.       add ( prop_spacing_command        , "font"                , 000 ) ; --e
  5834.       add ( footers_command             , "footer"              , 000 ) ; --5
  5835.       add ( footnote_command            , "foot_note"           , 000 ) ; --ec
  5836.       add ( forward_printing_command    , "forward_printing"    , 000 ) ;
  5837.       add ( footnote_command            , "fnote"               , 000 ) ;
  5838.       add ( go_left_command             , "go_left"             , 000 ) ; --e
  5839.       add ( go_left_command             , "goleft"              , 000 ) ;
  5840.       add ( headers_command             , "header"              , 000 ) ;
  5841.       add ( underline_foothead_command  , "head_foot_underline_char",000);
  5842.       add ( head_foot_space_command     , "hfspacing"           , 000 ) ;
  5843.       add ( underscore_command          , "horizontal_line"     , 000 ) ; --e
  5844.       -- add ( shadow_printing_command     , "italic_printing"     , 000 ) ; --e
  5845.       add ( index_command               , "idx"                 , 000 ) ;
  5846.       add ( if_command                  , "if"                  , 000 ) ; --e
  5847.       add ( ifswitch_command            , "if_switch"           , 000 ) ; --e
  5848.       add ( indexfile_command           , "ifile"               , 000 ) ; 
  5849.       add ( ifswitch_command            , "ifswitch"            , 000 ) ;
  5850.       add ( insert_command              , "include_file"        , 000 ) ;
  5851.       add ( indent_command              , "indent"              , 000 ) ; --5
  5852.       add ( index_command               , "index"               , 000 ) ; --ec
  5853.       add ( indexfile_command           , "index_file"          , 000 ) ; --ec
  5854.       add ( insert_command              , "insert_file"         , 000 ) ;
  5855.       add ( justify_margins_command     , "justify_margins"     , 000 ) ; --5
  5856.       add ( justify_numbers_command     , "just_numbers"        , 000 ) ; --ec
  5857.     end build_command_tree_2 ;
  5858.      
  5859.     procedure build_command_tree_3 is
  5860.     begin -- build_command_tree_3
  5861.       add ( left_margin_command         , "left_margin_in_tenths",000 ); --e
  5862.       add ( lcrm_command                , "lcrm"                , 000 ) ;
  5863.       add ( vert_line_spacing_command   , "line_point_spacing"  , 000 ) ; --ec
  5864.       add ( left_margin_command         , "lmargin_in_tenths"   , 000 ) ;
  5865.       -- add ( mult_line_spacing_command   , "multiple_line_spacing",000 );
  5866.       add ( date_mdy_command            , "mdy"                 , 000 ) ;
  5867.       add ( date_slash_command          , "m/d/y"               , 000 ) ;
  5868.       add ( date_dash_command           , "m-d-y"               , 000 ) ;
  5869.       add ( new_para_command            , "new_paragraph"       , 000 ) ;
  5870.       add ( indent_neg_command          , "negative_indent"     , 000 ) ;
  5871.       add ( para_indent_command         , "pindent"             , 000 ) ;
  5872.       add ( page_numbering_command      , "page_numbering"      , 000 ) ; --e
  5873.       add ( paper_length_command        , "paper_length_in_sixths",000 );
  5874.       add ( paper_width_command         , "paper_width_in_tenths",000 ) ; --ec
  5875.       add ( para_indent_command         , "paragraph_indent"    , 000 ) ; --e
  5876.       add ( pause_command               , "pause"               , 000 ) ;
  5877.       add ( char_width_command          , "points_per_character", 000 ) ;
  5878.       add ( printer_control_command     , "printer_dumb"        , 000 ) ; --x
  5879.       -- add ( right_margin_command        , "right_margin_in_tenths",000 ); --e
  5880.       add ( rclm_command                , "rclm"                , 000 ) ;
  5881.       add ( read_command                , "read_line_from_keyboard",000);
  5882.       add ( ribbon_color_command        , "red_ribbon"          , 000 ) ;
  5883.       add ( justify_rtmargin_command    , "right_justify"       , 000 ) ; --ec
  5884.       add ( justify_rtmargin_command    , "rjust"               , 000 ) ;
  5885.       add ( right_margin_command        , "rmargin_in_tenths"   , 000 ) ;
  5886.     end build_command_tree_3 ;
  5887.  
  5888.     procedure build_command_tree_4 is
  5889.     begin -- build_command_tree_4
  5890.       -- add ( subpara_command             , "subparagraph"        , 000 ) ; --4
  5891.       add ( line_save_command           , "save_lines"          , 000 ) ;
  5892.       add ( same_line_command           , "same_line_again"     , 000 ) ;
  5893.       add ( page_numbering_command      , "set_page_number"     , 000 ) ; --x
  5894.       add ( section_page_numbering_command,"section_numbering"  , 000 ) ; --e
  5895.       add ( section_page_numbering_command,"set_section_number" , 000 ) ; --x
  5896.       add ( switch_command              , "set_switch"          , 000 ) ; --ec
  5897.       add ( shadow_printing_command     , "shadow_printing"     , 000 ) ;
  5898.       add ( bold_character_command      , "sig_bold_character"  , 000 ) ;
  5899.       add ( dot_lead_command        , "sig_dot_leader_character", 000 );
  5900.       add ( forced_space_character_command,"sig_forced_space_char",000 );
  5901.       add ( underline_foothead_command  ,"sig_head_foot_und_char",000 );
  5902.       add ( shadow_character_command    , "sig_italic_character", 000 ) ;
  5903.       add ( shadow_character_command    , "sig_shadow_character", 000 ) ;
  5904.       add ( hypen_command               , "sig_soft_hyphen_char", 000 ) ;
  5905.       add ( subscript_command        , "sig_subscript_character", 000 );
  5906.       add ( superscript_command    , "sig_superscript_character", 000 );
  5907.       add ( temporary_font_character_command,"sig_temp_font_character",000 );
  5908.       add ( underline_character_command,"sig_underline_character",000 ) ;
  5909.       add ( ucontinuous_character_command,"sig_ucont_character" , 000 ) ;
  5910.       add ( hypen_command               , "soft_hyphen_character",000 );
  5911.       add ( subscript_command           , "subscript_character" , 000 ) ;
  5912.       add ( superscript_command        , "superscript_character", 000 );
  5913.       add ( switch_command              , "switch"              , 000 ) ; 
  5914.     end build_command_tree_4 ;
  5915.      
  5916.     procedure build_command_tree_5 is
  5917.     begin -- build_command_tree_5 
  5918.       add ( top_margin_command          , "tmargin_in_sixths"   , 000 ) ;
  5919.       add ( tabs_command           , "tab_to_character_position", 000 );
  5920.       add ( top_margin_command          , "top_margin_in_sixths", 000 ) ; --e
  5921.       -- add ( underline_chars_command     , "underline_characters", 000 ) ;
  5922.       add ( underline_cont_command      , "ucontinuous"         , 000 ) ;
  5923.       add ( underline_foothead_command  , "ufoot_character"     , 000 ) ;
  5924.       add ( underscore_command          , "underscore"          , 000 ) ; --ec
  5925.       add ( vert_line_spacing_command   , "vertical_line_spacing",000 );
  5926.       -- add ( variable_data_command    , "variable_data_insertion", 000 );--x
  5927.       -- the above command is only loaded and available if the variable
  5928.       -- insertion option is requested...
  5929.       add ( tabs_vertical_command       , "vertical_tab_to_line", 000 ) ; --ec
  5930.       add ( tabs_vertical_command       , "vtab_to_line_number" , 000 ) ; 
  5931.       add ( paper_width_command         , "width_in_tenths"     , 000 ) ;
  5932.       add ( write_command           , "write_message_to_console", 000 );
  5933.       add ( date_ymd_command            , "ymd"                 , 000 ) ;
  5934.     end build_command_tree_5 ;
  5935.      
  5936.     begin -- initialize_printer_commands_globally is
  5937.       build_command_tree_1 ;
  5938.       build_command_tree_2 ;
  5939.       build_command_tree_3 ;
  5940.       build_command_tree_4 ;
  5941.       build_command_tree_5 ;
  5942.     end initialize_printer_commands_globally ;
  5943.      
  5944.     procedure tidy_up_and_output_filled_line 
  5945.                                 ( Last_Line_In_Paragraph : Boolean := False ) is
  5946.       -- we have a line sitting in Filling_Output_Line
  5947.       -- make sure all items are set, and then output it...
  5948.       -- then, clear for the next one...
  5949.      
  5950.       procedure review_underlining is
  5951.         -- work from posn 1 .. filling_output_line.character_count
  5952.         -- look at all positions in reverse order, and if any underlining
  5953.         -- appears under spaces or punctuation before (actually after) it
  5954.         -- appears under text, then turn it off...
  5955.         --  NOTE : underlining punctuation is only possible if und continuous
  5956.         --         is selected and the punctuation is not at its very end, or
  5957.         --         at the end of a line (last characters) 
  5958.        
  5959.         we_have_underlined_text : boolean := false   ;
  5960.         cc                      : extended_character ;
  5961.         it_is_text              : boolean            ;
  5962.         extended_exclam    : constant extended_character 
  5963.                              := extended_character ( character'pos( '!' ) ) ;
  5964.         extended_period    : constant extended_character
  5965.                              := extended_character ( character'pos( '.' ) ) ;
  5966.         extended_comma     : constant extended_character
  5967.                              := extended_character ( character'pos( ',' ) ) ;
  5968.         extended_question  : constant extended_character
  5969.                              := extended_character ( character'pos( '?' ) ) ;
  5970.       begin -- review_underlining
  5971.         for posn in reverse 1 .. filling_output_line.character_count loop
  5972.           if filling_output_line.underline ( posn ) then
  5973.             -- we are working within an underlined area...
  5974.             if we_have_underlined_text then
  5975.               null ; -- it is ok, we already saw underlined text
  5976.             else
  5977.               -- here we either have a underline to turn off or else
  5978.               -- are just now moving into underlined text
  5979.               cc := filling_output_line.the_character ( posn ) ;
  5980.            -- it_is_text :=
  5981.            --          ( ( cc >= extended_zero ) and ( cc <= extended_nine ) )
  5982.            --  or else ( ( cc >= extended_UC_A ) and ( cc <= extended_UC_Z ) )
  5983.            --  or else ( ( cc >= extended_lc_a ) and ( cc <= extended_lc_z ) ) ;
  5984.               it_is_text := not (         ( cc = extended_space    )
  5985.                                   or else ( cc = extended_period   )
  5986.                                   or else ( cc = extended_comma    )
  5987.                                   or else ( cc = extended_exclam   )
  5988.                                   or else ( cc = extended_question ) ) ;
  5989.               -- the above implementation just turns it off on trailing
  5990.               -- spaces, periods, exclamation points, and question marks
  5991.               if it_is_text then
  5992.                 -- ok, good change to underlining...
  5993.                 we_have_underlined_text := true ;
  5994.               else
  5995.                 -- we want to modify this back
  5996.                 filling_output_line.underline ( posn ) := false ;
  5997.               end if ;
  5998.             end if ;
  5999.           elsif we_have_underlined_text then
  6000.             -- just moved off of underlining ...
  6001.             we_have_underlined_text := false ;
  6002.           end if ;
  6003.         end loop ;
  6004.       end review_underlining ;
  6005.        
  6006.     begin -- tidy_up_and_output_filled_line
  6007.       -- work on it if justify is set...
  6008.       if Current_Formatting_Parameters.Justification_On 
  6009.       and then last_line_in_paragraph then
  6010.         -- don't justify...
  6011.         filling_output_line.justify_to := filling_output_line.stop_position;
  6012.       end if ;
  6013.       -- now, if we did any special options, we must review line for correct
  6014.       -- underlining...
  6015.       if filling_output_line.special_options then
  6016.         review_underlining ;
  6017.       end if ;
  6018.       output_a_line ( filling_output_line ) ;
  6019.       filling_output_line.all := blank_output_line ;
  6020.       filling_trailing_spaces := 0 ;
  6021.       -- later we might want to try to set items selectively based upon
  6022.       -- old data values, etc.
  6023.       text_waiting_inside_filled_paragraph := false ;
  6024.       if last_line_in_paragraph then
  6025.         -- we must change the character changes back to the permanent
  6026.         -- settings, and with filling on, that happens when we hit the
  6027.         -- end of a paragraph
  6028.         current_formatting_parameters.current_character_changes
  6029.                  := current_formatting_parameters.permanent_character_changes ;
  6030.       end if ;
  6031.     end tidy_up_and_output_filled_line ;
  6032.      
  6033.   Procedure Options ( Return_Input_Line_Contains_Text : out boolean ) is
  6034.     input_line_contains_text : boolean := false ;
  6035.     temp_num : integer ;
  6036.     successfull : boolean ;
  6037.  
  6038.     procedure do_set_page_number ( working_section_number : boolean 
  6039.                                                             := false ) is
  6040.       --  1 Apr 85
  6041.       -- // .cmd off   //  
  6042.       --              turns page number display off
  6043.       --              and sets prefix/suffix to blank
  6044.       -- // .cmd on    //
  6045.       --              turns page number display on
  6046.       -- // .cmd default //
  6047.       --              sets all values to default values, disp. off
  6048.       -- // .cmd TB LRCA NUM PS
  6049.       -- // where TB is top/bottom or empty, meaning leave at
  6050.       --                                     the current setting
  6051.       -- // where LRCA is left/right/center/alternate or empty //
  6052.       -- // where NUM is n , +n , or -n for page number
  6053.       -- // where PS is the Prefix/Suffix string for the page
  6054.       --                                  number.  enclosed in 
  6055.       --                                  quotes, with a $ where
  6056.       --                                  the page number goes
  6057.       --
  6058.       --  examples:   .page top center 1 "Section 2-$"
  6059.       --              .page 1 "Section 3-$"
  6060.       --              .page bottom alternate
  6061.       --
  6062.       -- minimum value is 0         for  envelope feed
  6063.       -- maximum value is 32000     for page 32000
  6064.       -- DEFAULTS:    Top or Bottom => BOTTOM
  6065.       --              Left/Right/Ctr=> CENTER
  6066.       --              Start with    => Page 1
  6067.       --              Prefix/Suffix => None
  6068.       --              Show Page Num => Off
  6069.       orig_page_num : integer ;
  6070.      
  6071.       procedure pg_num ( modif : modifier_type ) is
  6072.       begin -- pg_num
  6073.         case modif is
  6074.           when top_modifier         => Current_Document_Parameters
  6075.                                           .number_page_at_top := true      ;
  6076.           when bottom_modifier      => Current_Document_Parameters
  6077.                                           .number_page_at_top := false     ;
  6078.           when left_modifier        => Current_Document_Parameters
  6079.                                           .page_number_goes := left_side   ;
  6080.           when right_modifier       => Current_Document_Parameters
  6081.                                           .page_number_goes := right_side  ;
  6082.           when center_modifier      => Current_Document_Parameters
  6083.                                           .page_number_goes := center      ;
  6084.           when alternating_modifier => Current_Document_Parameters
  6085.                                           .page_number_goes := alternating ;
  6086.           when others               => null ; 
  6087.         end case ;
  6088.       end pg_num ;
  6089.        
  6090.     begin -- do_set_page_number
  6091.       if ( modifier_one = on_modifier )
  6092.       or ( modifier_one = off_modifier ) 
  6093.       or ( modifier_one = default_modifier ) then
  6094.         if modifier_two /= no_modifier then
  6095.           command_error ( "Cannot have multiple parameters with"
  6096.                           & " this first parameter." , true ) ;
  6097.         elsif numeric_contents /= no_numeric_contents then
  6098.           command_error ( "Cannot have numeric parameters with"
  6099.                           & " this first parameter." , true ) ;
  6100.         elsif length( text_parameters ) /= 0 then
  6101.           command_error ( "Cannot have Text parameters with"
  6102.                           & " this first parameter." , true ) ;
  6103.         else
  6104.           -- we are ok...
  6105.           case modifier_one is
  6106.             when on_modifier       => current_document_parameters
  6107.                                       .page_numbering_on := true ;
  6108.                                       current_document_parameters
  6109.                                       .section_numbering_on
  6110.                                                   := working_section_number;
  6111.             when off_modifier      => current_document_parameters
  6112.                                       .page_numbering_on := false ;
  6113.                                       current_document_parameters
  6114.                                       .section_numbering_on:= false;
  6115.                                       set_length ( 
  6116.                                       current_document_parameters
  6117.                                       .page_prefix_suffix , 0   ) ;
  6118.             when default_modifier  => current_document_parameters
  6119.                                       .page_numbering_on := false ;
  6120.                                       current_document_parameters
  6121.                                       .current_page_number := 1   ;
  6122.                                       current_document_parameters
  6123.                                       .section_numbering_on:= false;
  6124.                                       current_document_parameters
  6125.                                       .current_section_num   := 1 ;
  6126.                                       current_document_parameters
  6127.                                       .number_page_at_top :=false ;
  6128.                                       current_document_parameters
  6129.                                       .page_number_goes := center ;
  6130.                                       set_length ( 
  6131.                                       current_document_parameters
  6132.                                       .page_prefix_suffix , 0   ) ;
  6133.             when others            => null ; -- can't get here
  6134.           end case ;
  6135.         end if ;
  6136.       else
  6137.         -- first modifier is not on/off/default
  6138.         if ( modifier_two = on_modifier )
  6139.         or ( modifier_two = off_modifier ) 
  6140.         or ( modifier_two = default_modifier ) then
  6141.           command_error ( "Cannot have multiple parameters with"
  6142.                             & " this second parameter." , true ) ;
  6143.         else
  6144.           -- we get here knowing that we do not have on/off/default
  6145.           allow_options ( false ,
  6146.                     o_any_numeric ,
  6147.                     o_top_bottom  ,
  6148.                     o_l_r_c_alt   ,
  6149.                     o_text_param  ) ;
  6150.           -- we get here knowing that we do not have conflicting
  6151.           -- parameters
  6152.           orig_page_num := Current_Document_Parameters.Current_Page_Number ;
  6153.           Current_Document_Parameters.Page_Numbering_On := true ;
  6154.           Current_Document_Parameters.Section_Numbering_On 
  6155.                                   := working_section_number ;
  6156.           -- First: work modifier_one
  6157.           pg_num ( modifier_one ) ;
  6158.           -- Then:  work modifier_two
  6159.           pg_num ( modifier_two ) ;
  6160.           -- Then:  work numeric
  6161.           if numeric_contents /= no_numeric_contents then
  6162.             If working_section_number then
  6163.               Current_Document_Parameters.Current_Section_Num
  6164.                 := new_value ( Current_Document_Parameters.Current_Section_Num,
  6165.                                 0 , 32000 , 1 ) ;
  6166.              
  6167.             else
  6168.               Current_Document_Parameters.Current_Page_Number
  6169.                 := new_value ( Current_Document_Parameters.Current_Page_Number,
  6170.                                 0 , 32000 , 1 ) ;
  6171.             end if ;
  6172.           end if ;
  6173.           -- Then:  work Text parameters
  6174.           if length( text_parameters ) > 0 then
  6175.             -- we must check for the placement of the number
  6176.             if position ( '$' , text_parameters ) = 0 then
  6177.               command_error ( "Page number string must contain '$'." , true ) ;
  6178.             end if ;
  6179.           end if ;
  6180.           Current_Document_Parameters.Page_Prefix_Suffix := text_parameters ;
  6181.           -- Finally, check to see what effect this page number change will
  6182.           -- have on our printing request
  6183.           if Current_Environment.First_Page_to_Print > orig_page_num 
  6184.                                   -- we haven't printed anything yet
  6185.           and ( Current_Document_Parameters.Current_Page_Number 
  6186.                   >= Current_Environment.First_Page_to_Print ) then
  6187.                                   -- and is at or past the first page to print
  6188.             Current_Environment.First_Page_to_Print 
  6189.                 := Current_Document_Parameters.Current_Page_Number ;
  6190.                                   -- then set the first page to print to
  6191.                                   -- be this page number....
  6192.           end if ;
  6193.         end if ;
  6194.       end if ;
  6195.       reset_vertical_physical_page_limits ;
  6196.     end do_set_page_number ;
  6197.    
  6198.     Procedure Month_Out ( month_command : text_formatter_command ) is
  6199.       space : constant character := ' ' ;
  6200.       today  : basic_io_system.timer ;
  6201.       nmonth : string(1..9) ;
  6202.       subtype str2 is string ( 1 .. 2 ) ;
  6203.       day_str , month_str , year_str : str2 ;
  6204.       Input_String : string ( 1 .. 30 ) ;
  6205.       Input_String_Length : integer ;
  6206.       pos_to_work : integer ;
  6207.       next_place  : integer ;
  6208.        
  6209.       Procedure To_Two_Digit_String( number : in  integer  ; 
  6210.                                      strg   : out str2     ) is
  6211.         new_num : integer := number ;
  6212.         ch : character ;
  6213.           
  6214.         Procedure fix( num : in out integer ) is
  6215.           -- this routine takes a number and returns the number / 10
  6216.           -- and a character which is the last digit in the number
  6217.         begin
  6218.           ch := character'val(48 + (num mod 10)) ;
  6219.           num := num / 10 ;
  6220.         end fix ;
  6221.         
  6222.       begin -- To_Two_Digit_String
  6223.         fix(new_num);
  6224.         strg(2) := ch ;
  6225.         fix(new_num);
  6226.         strg(1) := ch ;
  6227.       end To_Two_Digit_String ;
  6228.         
  6229.       Procedure move( s : in str2 ; c : in character ; place : in integer ) is
  6230.       begin
  6231.         Input_String(place  )        := s(1) ;
  6232.         Input_String(place+1)        := s(2) ;
  6233.         Input_String(place+2)        := c ;
  6234.       end move ;
  6235.           
  6236.     begin -- Month_Out
  6237.       today := basic_io_system.clock ;
  6238.       case today.month is
  6239.         when  1 => nmonth := "January  " ;
  6240.         when  2 => nmonth := "February " ;
  6241.         when  3 => nmonth := "March    " ;
  6242.         when  4 => nmonth := "April    " ;
  6243.         when  5 => nmonth := "May      " ;
  6244.         when  6 => nmonth := "June     " ;
  6245.         when  7 => nmonth := "July     " ;
  6246.         when  8 => nmonth := "August   " ;
  6247.         when  9 => nmonth := "September" ;
  6248.         when 10 => nmonth := "October  " ;
  6249.         when 11 => nmonth := "November " ;
  6250.         when 12 => nmonth := "December " ;
  6251.       end case ;
  6252.       To_Two_Digit_String ( today.day   , day_str   ) ;
  6253.       To_Two_Digit_String ( today.month , month_str ) ;
  6254.       To_Two_Digit_String ( today.year  , year_str  ) ;
  6255.       for posn in 1 .. 30 loop
  6256.         Input_String(posn) := space ;
  6257.       end loop ;
  6258.       case month_command is 
  6259.         when date_mdy_command     =>
  6260.                     -- set up Input_String as month day, year
  6261.                   for posn in 1 .. 9 loop
  6262.                     Input_String(posn) := nmonth(posn) ;
  6263.                   end loop ;
  6264.                   pos_to_work := 9 ;
  6265.                   while Input_String(pos_to_work) = ' ' loop
  6266.                     pos_to_work := pos_to_work - 1 ;
  6267.                   end loop ;
  6268.                   if day_str(1) = '0' then
  6269.                     day_str(1) := space ;
  6270.                     pos_to_work := pos_to_work + 1 ; 
  6271.                     -- because it includes the space
  6272.                   else
  6273.                     pos_to_work := pos_to_work + 2 ;
  6274.                   end if ;
  6275.                   move(day_str , ',' , pos_to_work) ;
  6276.                   Input_String(pos_to_work+4) := '1' ;
  6277.                   Input_String(pos_to_work+5) := '9' ;
  6278.                   move(year_str , ' ' , pos_to_work+6) ;
  6279.                   Input_String_Length := pos_to_work + 7 ;
  6280.          
  6281.         when date_dmy_command     =>
  6282.                   -- set up Input_String as dd mmm yy
  6283.                   move(day_str , ' ' , 1) ;
  6284.                   for posn in 1 .. 3 loop
  6285.                     Input_String(posn+3) := nmonth(posn) ;
  6286.                   end loop ;
  6287.                   move(year_str , ' ' , 8) ;
  6288.                   Input_String_Length := 9 ;
  6289.          
  6290.         when date_ymd_command     =>
  6291.                   -- set up Input_String as yymmdd
  6292.                   move(year_str , space , 1) ;
  6293.                   move(month_str , space , 3) ;
  6294.                   move(day_str, space , 5) ;
  6295.                   Input_String_Length := 6 ;
  6296.          
  6297.         when date_slash_command
  6298.            | date_dash_command    =>
  6299.                   -- set up Input_String as mm/dd/yy or mm-dd-yy 
  6300.                   if month_str(1) = '0' then
  6301.                     Input_String(1) := month_str(2) ;
  6302.                     next_place := 2 ;
  6303.                   else
  6304.                     move(month_str , space , 1) ;
  6305.                     next_place := 3 ;
  6306.                   end if;
  6307.                   if month_command = date_slash_command then
  6308.                     Input_String(next_place) := '/' ;
  6309.                   else
  6310.                     Input_String(next_place) := '-' ;
  6311.                   end if ;
  6312.                   pos_to_work := next_place ;
  6313.                   next_place := next_place + 1 ;
  6314.                   if day_str(1) = '0' then
  6315.                     Input_String(next_place) := day_str(2) ;
  6316.                     next_place := next_place + 1 ;
  6317.                   else
  6318.                     move(day_str , space , next_place) ;
  6319.                     next_place := next_place + 2 ;
  6320.                   end if ;
  6321.                   Input_String(next_place) := Input_String(pos_to_work) ; 
  6322.                               -- get the last break character
  6323.                   move(year_str , space , next_place+1) ;
  6324.                   Input_String_Length := next_place + 3 ;
  6325.         when others => null ; -- can't get here
  6326.       end case ;
  6327.       -- now, we need to move it over.....
  6328.       force_into_input_stream ( 
  6329.           string_to_pstring ( input_string ( 1 .. input_string_length ) ) ,
  6330.                                 input_line_contains_text ) ;
  6331.     end Month_Out ;
  6332.      
  6333.     procedure do_write_command is
  6334.     begin -- do_write_command
  6335.       -- move text parameters out as a prompt
  6336.       clear_end_of_screen( master_window , 20 , 1 ) ;
  6337.       goto_line_column ( master_window , 20 , 1 ) ;
  6338.       put( text_parameters ) ;
  6339.     end do_write_command ;
  6340.      
  6341.     procedure do_read_command is
  6342.       f_string , s_string , d_string : pstring ;
  6343.       in_length : integer ;
  6344.     begin -- do_read_command
  6345.       set_length(s_string , 76) ;
  6346.       for i in 1 .. 76 loop
  6347.         s_string.data(i) := ' ' ;
  6348.       end loop ;
  6349.       f_string := s_string ;
  6350.       d_string := s_string ;
  6351.       s_string := string_read(f_string , d_string , 76 , 2 , 22 ) ;
  6352.       clear_end_of_screen (master_window , 20 , 1     ) ;
  6353.       s_string := compress ( s_string ) ;
  6354.       force_into_input_stream ( s_string , input_line_contains_text ) ;
  6355.     end do_read_command ;
  6356.      
  6357.     procedure work_character_command is
  6358.       -- we have a character to change a command option
  6359.       md : modifier_type := modifier_one ;
  6360.      
  6361.       procedure c ( item : a_char_type ) is
  6362.         cc : extended_character 
  6363.              := extended_character( character'pos( text_parameters.data(1) ) ) ;
  6364.       begin -- c
  6365.         -- first, check to see that no other item uses this character...
  6366.         if cc = extended_space then
  6367.           cc := extended_nul ; -- just a rule, a space maps to a nul for this
  6368.         end if ;
  6369.         if cc /= extended_nul then
  6370.           -- must check it...
  6371.           if char_types ( cc ) = item then
  6372.             return ; -- we are setting to the same old value....
  6373.           elsif char_types ( cc ) /= Illegal_Character 
  6374.           and then char_types ( cc ) /= Text_Character then
  6375.             -- this character is already used.
  6376.             command_error ( 
  6377.          "This Command Character is already used by another command." , true ) ;
  6378.           end if ;
  6379.         end if ;
  6380.         -- then, we need to un-map the old value that we used for this item
  6381.         if current_characters_array ( item ) /= extended_nul then
  6382.           char_types ( current_characters_array ( item ) ) := Text_Character ;
  6383.         end if ;
  6384.         -- Now, set the mapping from command to character 
  6385.         current_characters_array ( item ) := cc ;
  6386.         -- Finally, set the mapping from character to command
  6387.         char_types ( cc ) := item ;
  6388.       end c ;
  6389.      
  6390.     begin -- work_character_command
  6391.       if length( text_parameters ) /= 1 then
  6392.         command_error ( "Single Character Parameter required." , true ) ;
  6393.       end if ;
  6394.       case command is
  6395.         when hypen_command                  =>   c ( Soft_Hyphen        ) ;
  6396.         when dot_lead_command               =>   c ( Dot_Leader         ) ;
  6397.         when subscript_command              => if md = on_modifier then
  6398.                                                  c ( Subscript_Start    ) ;
  6399.                                                elsif md = off_modifier then 
  6400.                                                  c ( Subscript_Stop     ) ;
  6401.                                                else -- is toggle modifier
  6402.                                                  c ( Subscript_Toggle   ) ;
  6403.                                                end if ;
  6404.         when superscript_command            => if md = on_modifier then
  6405.                                                  c ( Superscript_Start  ) ;
  6406.                                                elsif md = off_modifier then 
  6407.                                                  c ( Superscript_Stop   ) ;
  6408.                                                else -- is toggle modifier
  6409.                                                  c ( Superscript_Toggle ) ;
  6410.                                                end if ;
  6411.         when underline_foothead_command     => if md = on_modifier then
  6412.                                                  c ( UFoot_Start        ) ;
  6413.                                                elsif md = off_modifier then 
  6414.                                                  c ( UFoot_Stop         ) ;
  6415.                                                else -- is toggle modifier
  6416.                                                  c ( UFoot_Toggle       ) ;
  6417.                                                end if ;
  6418.         when underline_character_command    => if md = on_modifier then
  6419.                                                  c ( Underline_Start    ) ;
  6420.                                                elsif md = off_modifier then 
  6421.                                                  c ( Underline_Stop     ) ;
  6422.                                                else -- is toggle modifier
  6423.                                                  c ( Underline_Toggle   ) ;
  6424.                                                end if ;
  6425.         when ucontinuous_character_command  => if md = on_modifier then
  6426.                                                  c ( UCont_Start        ) ;
  6427.                                                elsif md = off_modifier then 
  6428.                                                  c ( UCont_Stop         ) ;
  6429.                                                else -- is toggle modifier
  6430.                                                  c ( UCont_Toggle       ) ;
  6431.                                                end if ;
  6432.         when bold_character_command         => if md = on_modifier then
  6433.                                                  c ( Bold_Start         ) ;
  6434.                                                elsif md = off_modifier then 
  6435.                                                  c ( Bold_Stop          ) ;
  6436.                                                else -- is toggle modifier
  6437.                                                  c ( Bold_Toggle        ) ;
  6438.                                                end if ;
  6439.         when shadow_character_command       => if md = on_modifier then
  6440.                                                  c ( Shadow_Start       ) ;
  6441.                                                elsif md = off_modifier then 
  6442.                                                  c ( Shadow_Stop        ) ;
  6443.                                                else -- is toggle modifier
  6444.                                                  c ( Shadow_Toggle      ) ;
  6445.                                                end if ;
  6446.         when temporary_font_character_command => if md = on_modifier then
  6447.                                                 c ( Temp_Font_Start    ) ;
  6448.                                                elsif md = off_modifier then 
  6449.                                                 c ( Temp_Font_Stop     ) ;
  6450.                                                else -- is toggle modifier
  6451.                                                 c ( Temp_Font_Toggle   ) ;
  6452.                                                end if ;
  6453.         when forced_space_character_command =>  c ( Forced_Space       ) ;
  6454.         when others => null ; -- cannot get here..... this routine is only
  6455.                               -- called with one of the specified params
  6456.       end case ; 
  6457.     end work_character_command ;
  6458.      
  6459.     procedure set_formatting( Opt: permanent_and_temporary_character_changes ;
  6460.                               check_twice : boolean := true ) is
  6461.     begin -- set_formatting 
  6462.       current_formatting_parameters.permanent_character_changes ( opt )
  6463.                                              := ( modifier_one = on_modifier ) ;
  6464.       current_formatting_parameters.current_character_changes   ( opt ) 
  6465.                                              := ( modifier_one = on_modifier ) ;
  6466.       if check_twice 
  6467.       and then modifier_one = off_modifier then
  6468.         -- we need to check for underline on and the wrong type of underlining
  6469.         -- turned off...
  6470.         if opt = underline then
  6471.           set_formatting ( underline_continuous , false ) ;
  6472.         elsif opt = underline_continuous then
  6473.           set_formatting ( underline , false ) ;
  6474.         end if ;
  6475.       end if ;
  6476.     end set_formatting ;
  6477.      
  6478.     Procedure check_file_name ( fname           : in out pstring ;
  6479.                                 Input_File      : boolean        ;
  6480.                                 Delete_If_Exists: boolean        ;
  6481.                                 Default_Ending  : string         ) is
  6482.       -- take in a file name and append the default ending if it
  6483.       -- does not contain the first character in the default ending.
  6484.       -- if it does contain that character, and that character is the
  6485.       -- last character in the name, then delete that last character 
  6486.     begin  -- check_file_name
  6487.       fname := compress ( fname ) ;
  6488.       if default_ending'length > 0 then
  6489.         if position ( default_ending(1) , fname ) = 0 then
  6490.           fname := fname & Default_Ending ;
  6491.         elsif position ( default_ending(1) , fname ) = length ( fname ) then
  6492.           set_length ( fname , length( fname ) - 1 ) ;
  6493.         end if ;
  6494.       end if ;
  6495.       if Input_File then
  6496.         -- input file 
  6497.         if not file_exists ( fname ) then
  6498.           command_error ( "File does not exist." , true ) ;
  6499.         end if ;
  6500.       else
  6501.         -- output file 
  6502.         if file_exists ( fname ) then
  6503.           if delete_if_exists then
  6504.             do_purge ( fname ) ;
  6505.           else
  6506.             command_error ( "File already exists." , true ) ;
  6507.           end if ;
  6508.         end if ;
  6509.       end if ;
  6510.     end check_file_name ;
  6511.      
  6512.     function to_ascii ( s : pstring ) return ascii_text_file_name is
  6513.       fname : ascii_text_file_name := no_file ;
  6514.     begin -- to_ascii
  6515.       for posn in 1 .. length(s) loop
  6516.         fname ( posn ) := s.data ( posn ) ;
  6517.       end loop ;
  6518.       return fname ;
  6519.     end to_ascii ;
  6520.      
  6521.     procedure do_insert_command is
  6522.     begin -- do_insert_command
  6523.       if where_to_read = alternate_input_file then
  6524.         command_error (
  6525.           "An Include File may not call for another include file.", true );
  6526.       end if ;
  6527.       allow_options ( exactly_one , o_text_param ) ;
  6528.       check_file_name( text_parameters , 
  6529.                        true            , -- input file ?
  6530.                        false           , -- delete if output file?
  6531.                        ".TXT"        ) ; -- default ending
  6532.       -- we only get here if we are ok, otherwise command_error
  6533.       -- was called....
  6534.       alt_in_file_name := to_ascii ( text_parameters ) ;
  6535.       open_for_read ( alternate_input_file ,
  6536.                       alt_in_file_name     , successfull ) ;
  6537.       if not successfull then
  6538.         command_error ( "Cannot Open Include File." , true ) ;
  6539.       end if ;
  6540.       select_for_read( alternate_input_file ) ;
  6541.        
  6542.       If Initial_Environment.Show_Output_Status 
  6543.       and then Initial_Environment.Where_To /= To_Screen then
  6544.         -- otsxy( 15 ,  4 , "Included File Title"  ) ;
  6545.         set_reverse(true);
  6546.         otsxy( 39 ,  4 , ' ' & Alt_In_File_Name & ' ' ) ;
  6547.         set_reverse(false);
  6548.         goto_line_column( master_window , 1 , 1 ) ;
  6549.       end if ;
  6550.      
  6551.     end do_insert_command ;
  6552.      
  6553.     procedure do_indexfile_command is
  6554.     begin -- do_indexfile_command 
  6555.       allow_options ( exactly_one , o_text_param ) ;
  6556.       check_file_name( text_parameters , 
  6557.                        false           , -- input file ?
  6558.                        true            , -- delete if output file?
  6559.                        ".IDX"        ) ; -- default ending
  6560.       -- we only get here if we are ok, otherwise command_error
  6561.       -- was called....
  6562.       if text_io.is_open(index_output_file) then
  6563.         text_io.close(index_output_file);
  6564.       end if ;
  6565.       index_file_name := to_ascii ( text_parameters ) ;
  6566.       open_for_write ( Index_Output_File , 
  6567.                        Index_File_Name   ,  successfull ) ;
  6568.       if not successfull then
  6569.         command_error ( "Cannot Create Index File." , true ) ;
  6570.       end if ;
  6571.       Index_File_Is_Open := true ;
  6572.        
  6573.       If Initial_Environment.Show_Output_Status 
  6574.       and then Initial_Environment.Where_To /= To_Screen then
  6575.         otsxy( 15 ,  6 , "Index File Title   "  ) ;
  6576.         set_reverse(true);
  6577.         otsxy( 39 ,  6 , ' ' & Index_File_Name & ' ' ) ;
  6578.         set_reverse(false);
  6579.         goto_line_column( master_window , 1 , 1 ) ;
  6580.       end if ;
  6581.      
  6582.     end do_indexfile_command ;
  6583.      
  6584.     procedure set_line_modification ( To_What : Line_Modification_Type ;
  6585.                                       Use_Command_Line : boolean ) is
  6586.       modf : modifier_type ;
  6587.     begin -- set_line_modification
  6588.       -- set line modification to center and use the current
  6589.       -- parsed command line...
  6590.       if use_command_line then
  6591.         allow_options ( exactly_one ,
  6592.                         o_on_off    ,
  6593.                         o_abs_numeric) ;
  6594.         temp_num := new_value ( 0 , 0 , 32000 , 1 ) ;
  6595.         -- min is 0 ( meaning off ) .. max is 32000 lines
  6596.         finish_current_text ;
  6597.         modf := modifier_one ;
  6598.       else
  6599.         modf := off_modifier ;
  6600.       end if ;
  6601.       if modf = off_modifier then
  6602.         Current_Formatting_Parameters.Line_Modification := Nothing ;
  6603.         If Current_Formatting_Parameters.Modification_Status /= Off then
  6604.           Current_Formatting_Parameters.Filling_On 
  6605.             := current_formatting_parameters.Fill_Before_Special ;
  6606.           Current_Formatting_Parameters.Justification_On 
  6607.             := current_formatting_parameters.Just_Before_Special ;
  6608.           Current_Formatting_Parameters.Modification_Status := Off ;
  6609.         end if ;
  6610.       else 
  6611.         Current_Formatting_Parameters.Line_Modification := To_What ;
  6612.         If Current_Formatting_Parameters.Modification_Status = Off then
  6613.           current_formatting_parameters.Fill_Before_Special 
  6614.               := Current_Formatting_Parameters.Filling_On ;
  6615.           current_formatting_parameters.Just_Before_Special 
  6616.               := Current_Formatting_Parameters.Justification_On ;
  6617.           Current_Formatting_Parameters.Filling_On := false ;
  6618.           Current_Formatting_Parameters.Justification_On := false ;
  6619.         end if ;
  6620.         if modf = on_modifier then
  6621.           Current_Formatting_Parameters.Modification_Status 
  6622.                             := Do_Forever ;
  6623.         else
  6624.           Current_Formatting_Parameters.Modification_Status 
  6625.                             := Do_While_Counting ;
  6626.           Current_Formatting_Parameters.Modify_To_Do := temp_num ;
  6627.         end if ;
  6628.       end if ;
  6629.     end set_line_modification ;
  6630.      
  6631.     procedure process_header_footer_lines ( Header_Footer : boolean        ;
  6632.                                             A_Header      : boolean        ;
  6633.                         Num_Lines : in out integer                         ;
  6634.                         Height    : in out vertical_measurement            ;
  6635.                         Ptr       : in out Heading_Or_Footing_line_pointer ) is
  6636.       tmp_ptr : heading_or_footing_line_pointer ;
  6637.       z_ptr   : heading_or_footing_line_pointer ;
  6638.       temporary_saved_formatting_parameters : formatting_parameters ;
  6639.     begin -- process_header_footer_lines
  6640.       -- we are processing those lines as specified by the .cmd n command
  6641.       allow_options ( false       , o_abs_numeric , o_off ) ;
  6642.       -- also allows no option, defaulting to mean off
  6643.       temp_num := new_value ( 0 , 0 , 66 , 1 ) ;
  6644.       -- min is 0 .. max is 66 lines
  6645.       -- now, we must process the beginning of header/footers vs. foot notes
  6646.       if header_footer then
  6647.         clear_a_list ( ptr ) ; -- if null, does nothing
  6648.         num_lines := temp_num ;
  6649.         Height    := 0 ;
  6650.         if num_lines = 0 then
  6651.           return ;
  6652.         else
  6653.           -- finally, set ptr ....
  6654.           Ptr := freelist_heading.get_from_free_list ;
  6655.           Tmp_Ptr := Ptr ;
  6656.         end if ;
  6657.       else
  6658.         if temp_num = 0 then
  6659.           return ;
  6660.         end if ;
  6661.         if num_lines = 0 then
  6662.           -- we must adjust it for the one inch line
  6663.           -- must set height to match the 
  6664.           -- that puts in the heading line
  6665.           -- '-----------------'
  6666.           -- also the blank line following it
  6667.           Height := 2 * current_document_parameters.Page_Heading_Footing_VMI ;
  6668.           Ptr := freelist_heading.get_from_free_list ;
  6669.           Tmp_Ptr := Ptr ;
  6670.         else
  6671.           -- height is ok as it stands...
  6672.           -- otherwise, ptr is already ok, but we need to move to the end of
  6673.           -- the list....
  6674.           Tmp_Ptr := Ptr ;
  6675.           loop
  6676.             z_ptr := next_line_ptr ( Tmp_Ptr ) ;
  6677.             -- that moved us to the next pointer in the list
  6678.           exit when z_ptr = null ; -- found end of list
  6679.             tmp_ptr := z_ptr ;
  6680.           end loop ;
  6681.           -- here with tmp_ptr as the last valid item in list
  6682.           set_next_ptr ( tmp_ptr ) ;
  6683.           tmp_ptr := next_line_ptr ( tmp_ptr ) ;
  6684.         end if ;
  6685.         num_lines := num_lines + temp_num ;
  6686.       end if ;
  6687.       -- set to no special formatting to take place...
  6688.       temporary_saved_formatting_parameters := current_formatting_parameters ;
  6689.       current_formatting_parameters         := blank_formatting_parameters   ;
  6690.       current_formatting_parameters.line_modification   := to_left_margin    ;
  6691.       current_formatting_parameters.Modification_Status := Do_Forever        ;
  6692.       in_header_or_footer := true ;
  6693.       -- here, tmp_ptr is pointing to an item ready for data
  6694.       for Line_Num in 1 .. temp_num loop
  6695.         load_input_line(false) ;
  6696.         Input_Line_To_Output_Line ;
  6697.         set_line_data ( tmp_ptr , waiting_output_line.all ) ;
  6698.         if Line_Num /= temp_num then
  6699.           set_next_ptr ( tmp_ptr ) ;
  6700.           tmp_ptr := next_line_ptr ( tmp_ptr ) ;
  6701.         end if ;
  6702.         Height := Height + current_document_parameters.Page_Heading_Footing_VMI;
  6703.       end loop ;
  6704.       if header_footer then
  6705.         height := height + current_document_parameters.page_heading_footing_vmi;
  6706.         -- for the blank line following a header and the blank line preceding
  6707.         -- the footer...
  6708.       end if ;
  6709.       -- reset special formatting to the correct setting...
  6710.       current_formatting_parameters := temporary_saved_formatting_parameters ;
  6711.       in_header_or_footer := false ;
  6712.     end process_header_footer_lines ;
  6713.      
  6714.     procedure do_set_head_foot_space is
  6715.       new_val : integer ;
  6716.     begin -- do_set_head_foor_space
  6717.       -- minimum 1 point
  6718.       -- maximum is number of vertical points per inch
  6719.       allow_options ( exactly_one , o_abs_numeric ) ;
  6720.       new_val  := new_value( 0, 1, printer_vertical_per_inch, 1 ) ;
  6721.       -- that call simply checks for within limits...
  6722.       -- first, we must modify each of the old heights
  6723.       temp_num := current_document_parameters.Footing_Height  ;
  6724.       temp_num := temp_num 
  6725.             / current_document_parameters.Page_Heading_Footing_VMI ;
  6726.       temp_num := temp_num * new_val ;
  6727.       current_document_parameters.Footing_Height  := temp_num ;
  6728.       temp_num := current_document_parameters.FootNote_Height ;
  6729.       temp_num := temp_num 
  6730.             / current_document_parameters.Page_Heading_Footing_VMI ;
  6731.       temp_num := temp_num * new_val ;
  6732.       current_document_parameters.FootNote_Height := temp_num ;
  6733.       temp_num := current_document_parameters.Heading_Height  ;
  6734.       temp_num := temp_num 
  6735.             / current_document_parameters.Page_Heading_Footing_VMI ;
  6736.       temp_num := temp_num * new_val ;
  6737.       current_document_parameters.Heading_Height  := temp_num ;
  6738.       reset_vertical_physical_page_limits ;
  6739.     end do_set_head_foot_space ;
  6740.      
  6741.     Procedure Fix_Up_Line is
  6742.       -- we think that we have text in the input line
  6743.       first_pos : integer ;
  6744.       old_pos   : integer ;
  6745.     begin  -- fix_up_line
  6746.       -- compress Input_Line
  6747.       -- first right half...
  6748.       loop
  6749.       exit when input_line_length = 0 ;
  6750.       exit when input_line ( input_line_length ) /= extended_space ;
  6751.         input_line_length := input_line_length - 1 ;
  6752.       end loop ;
  6753.       first_pos := 1 ;
  6754.       loop
  6755.       exit when first_pos > input_line_length ;
  6756.       exit when input_line ( first_pos ) /= extended_space ;
  6757.         first_pos := first_pos + 1 ;
  6758.       end loop ;
  6759.       if input_line_length < first_pos then
  6760.         input_line_contains_text := false ;
  6761.       else
  6762.         -- we have text to work
  6763.         -- first, move it over...
  6764.         if first_pos > 1 then
  6765.           for posn in first_pos .. input_line_length loop
  6766.             input_line ( posn - first_pos + 1 ) := Input_Line ( posn ) ;
  6767.           end loop ;
  6768.           input_line_length := Input_Line_Length - first_pos + 1 ;
  6769.         end if ;
  6770.         text_parameters := compress ( text_parameters ) ;
  6771.         if length ( Text_Parameters)  > 0 then
  6772.           -- we have to concat the current line and the text parameter
  6773.           if input_line_length > 3 then
  6774.             -- check for 's
  6775.             if map_up ( Input_Line(input_line_length) ) = extended_uc_s then
  6776.               if map_up ( Text_Parameters.data(2) ) = 'S' then
  6777.                 if Text_Parameters.data(1) = '''
  6778.                 or else Text_Parameters.data(1) = '`' then
  6779.                   for posn in 1 .. length ( Text_Parameters ) - 1 loop
  6780.                     Text_Parameters.data(posn) := Text_Parameters.data(posn+1) ;
  6781.                   end loop ;
  6782.                   set_length ( Text_Parameters , Length(Text_Parameters) - 1 );
  6783.                 end if ;
  6784.               end if ;
  6785.             end if ;
  6786.           end if ;
  6787.           old_pos := 1 ;
  6788.           loop
  6789.           exit when old_pos > length ( text_parameters ) ;
  6790.           exit when input_line_length = max_line_length  ;
  6791.             input_line_length := input_line_length + 1 ;
  6792.             Input_Line ( Input_line_length ) 
  6793.                 := extended_character ( character'pos (
  6794.                                         text_parameters.data ( old_pos ) ) ) ;
  6795.             old_pos := old_pos + 1 ;
  6796.           end loop ;
  6797.         end if ;
  6798.         -- xlate(option) ; -- translate if option, else just delete the ^
  6799.       end if ; -- no text parameter anyway...
  6800.     end fix_up_line ;
  6801.      
  6802.   begin -- options 
  6803.      
  6804.     return_input_line_contains_text := false ;
  6805.      
  6806.     Parse_Input_Command_Line ;
  6807.     Input_Line_Contains_Text := false ;
  6808.      
  6809.     case command is
  6810.        
  6811.       when paper_width_command            => 
  6812.                   -- 29 Mar 85 
  6813.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6814.                   -- // .cmd default //
  6815.                   -- n measured in 1/10"
  6816.                   -- minimum value is 10        for  1 inch
  6817.                   -- maximum value is 140       for 14 inches 
  6818.                   -- default value is 85        for  8.5 inches
  6819.                   finish_current_text ;
  6820.                   allow_options ( exactly_one ,
  6821.                                   o_any_numeric ) ;
  6822.                   temp_num := new_value ( current_physical_parameters
  6823.                                           .paper_width ,
  6824.                                           10 , 140 ,
  6825.                                           printer_points_per_inch / 10 ) ;
  6826.                   current_physical_parameters.paper_width := temp_num ;
  6827.                   reset_horizontal_physical_page_limits ;
  6828.        
  6829.       when paper_length_command           => 
  6830.                   -- 29 Mar 85 
  6831.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6832.                   -- // .cmd default //
  6833.                   -- n measured in 1/6"
  6834.                   -- minimum value is  0        for  no setting
  6835.                   -- maximum value is 84        for 14 inches
  6836.                   -- default value is 66        for 11 inches
  6837.                   finish_current_text ;
  6838.                   allow_options ( exactly_one ,
  6839.                                   o_any_numeric ) ;
  6840.                   temp_num := new_value ( current_physical_parameters
  6841.                                           .paper_length ,
  6842.                                           0 , 84 ,
  6843.                                           printer_vertical_per_inch / 6 ) ;
  6844.                   current_physical_parameters.paper_length := temp_num ;
  6845.                   execute_printer_command( set_form_length , temp_num ) ;
  6846.                   reset_vertical_physical_page_limits ;
  6847.        
  6848.       when left_margin_command            => 
  6849.                   -- 29 Mar 85 
  6850.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6851.                   -- // .cmd off   //
  6852.                   -- // .cmd default //
  6853.                   -- n measured in 1/10"
  6854.                   -- minimum value is  0        for  no left margin
  6855.                   -- maximum value is 140       for 14 inches
  6856.                   -- default value is 10        for  1 inch
  6857.                   finish_current_text ;
  6858.                   allow_options ( exactly_one ,
  6859.                                   o_any_numeric ,
  6860.                                   o_off ) ;
  6861.                   temp_num := new_value ( current_physical_parameters
  6862.                                           .left_margin ,
  6863.                                           0 , 140 ,
  6864.                                           printer_points_per_inch / 10 ) ;
  6865.                   current_physical_parameters.left_margin := temp_num ;
  6866.                   current_physical_parameters.real_left   := temp_num ;
  6867.                   reset_horizontal_physical_page_limits ;
  6868.        
  6869.       when right_margin_command           => 
  6870.                   -- 29 Mar 85 
  6871.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6872.                   -- // .cmd off   //
  6873.                   -- // .cmd default //
  6874.                   -- n measured in 1/10"
  6875.                   -- minimum value is  0        for  no right margin
  6876.                   -- maximum value is 140       for 14 inches
  6877.                   -- default value is 10        for  1 inch
  6878.                   finish_current_text ;
  6879.                   allow_options ( exactly_one ,
  6880.                                   o_any_numeric ,
  6881.                                   o_off ) ;
  6882.                   temp_num := new_value ( current_physical_parameters
  6883.                                           .right_margin,
  6884.                                           0 , 140 ,
  6885.                                           printer_points_per_inch / 10 ) ;
  6886.                   current_physical_parameters.right_margin:= temp_num ;
  6887.                   current_physical_parameters.real_right  := temp_num ;
  6888.                   reset_horizontal_physical_page_limits ;
  6889.        
  6890.       when top_margin_command             => 
  6891.                   -- 29 Mar 85 
  6892.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6893.                   -- // .cmd off   //
  6894.                   -- // .cmd default //
  6895.                   -- n measured in 1/6"
  6896.                   -- minimum value is  0        for  no top margin
  6897.                   -- maximum value is 84        for 14 inches
  6898.                   -- default value is 6         for  1 inch
  6899.                   finish_current_text ;
  6900.                   allow_options ( exactly_one ,
  6901.                                   o_any_numeric ,
  6902.                                   o_off ) ;
  6903.                   temp_num := new_value ( current_physical_parameters
  6904.                                           .top_margin ,
  6905.                                           0 , 84 ,
  6906.                                           printer_vertical_per_inch / 6 ) ;
  6907.                   current_physical_parameters.top_margin:= temp_num ;
  6908.                   reset_vertical_physical_page_limits ;
  6909.        
  6910.       when bottom_margin_command          => 
  6911.                   --  1 Apr 85
  6912.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6913.                   -- // .cmd off   //
  6914.                   -- // .cmd default //
  6915.                   -- n measured in 1/6"
  6916.                   -- minimum value is  0        for  no bottom margin
  6917.                   -- maximum value is 84        for 14 inches
  6918.                   -- default value is 6         for  1 inch
  6919.                   finish_current_text ;
  6920.                   allow_options ( exactly_one ,
  6921.                                   o_any_numeric ,
  6922.                                   o_off ) ;
  6923.                   temp_num := new_value ( current_physical_parameters
  6924.                                           .bottom_margin ,
  6925.                                           0 , 84 ,
  6926.                                           printer_vertical_per_inch / 6 ) ;
  6927.                   current_physical_parameters.bottom_margin:= temp_num ;
  6928.                   reset_vertical_physical_page_limits ;
  6929.        
  6930.       when binding_command                => 
  6931.                   --  1 Apr 85
  6932.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6933.                   -- // .cmd off   //
  6934.                   -- // .cmd default //
  6935.                   -- n measured in 1/10"
  6936.                   -- minimum value is  0        for  no binding edge
  6937.                   -- maximum value is 140       for 14 inches
  6938.                   -- default value is 0         for  off
  6939.                   finish_current_text ;
  6940.                   allow_options ( exactly_one ,
  6941.                                   o_any_numeric ,
  6942.                                   o_off ) ;
  6943.                   temp_num := new_value ( current_physical_parameters
  6944.                                           .binding_edge ,
  6945.                                           0 , 140 ,
  6946.                                           printer_points_per_inch / 10 ) ;
  6947.                   current_physical_parameters.binding_edge:= temp_num ;
  6948.                   reset_horizontal_physical_page_limits ;
  6949.        
  6950.       when subpara_command                => 
  6951.                   --  1 Apr 85
  6952.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6953.                   -- // .cmd off   //
  6954.                   -- // .cmd default //
  6955.                   -- n measured in the current font pitch
  6956.                   -- minimum value is - 140     for  negative 140 characters
  6957.                   -- maximum value is 140       for 140 characters
  6958.                   -- default value is 0         for  off
  6959.                   -- finish_current_text ;
  6960.                   allow_options ( exactly_one ,
  6961.                                   o_any_numeric ,
  6962.                                   o_off ) ;
  6963.                   temp_num := new_value ( current_formatting_parameters
  6964.                                           .left_indentation ,
  6965.                                           -140 , 140 ,
  6966.                                           font_width ) ;
  6967.                   current_formatting_parameters.left_indentation:=temp_num ;
  6968.                   horizontal_control_values_changed ;
  6969.        
  6970.       when go_left_command                => 
  6971.                   --  1 Apr 85
  6972.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6973.                   -- // .cmd off   //
  6974.                   -- // .cmd default //
  6975.                   -- n measured in the current font pitch
  6976.                   -- minimum value is - 140     for  negative 140 characters
  6977.                   -- maximum value is 140       for 140 characters
  6978.                   -- default value is 0         for  off
  6979.                   -- finish_current_text ;
  6980.                   allow_options ( exactly_one ,
  6981.                                   o_any_numeric ,
  6982.                                   o_off ) ;
  6983.                   temp_num := new_value ( current_formatting_parameters
  6984.                                           .right_indentation ,
  6985.                                           -140 , 140 ,
  6986.                                           font_width ) ;
  6987.                   current_formatting_parameters.right_indentation:=temp_num ;
  6988.                   horizontal_control_values_changed ;
  6989.        
  6990.       when indent_command                 => 
  6991.                   --  1 Apr 85
  6992.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  6993.                   -- // .cmd off   //
  6994.                   -- // .cmd default //
  6995.                   -- n measured in the current font pitch
  6996.                   -- minimum value is - 140     for  negative 140 characters
  6997.                   -- maximum value is 140       for 140 characters
  6998.                   -- default value is 0         for  off
  6999.                   -- Indent sets first line indentation, following = 0 
  7000.                   finish_current_text ;
  7001.                   allow_options ( exactly_one ,
  7002.                                   o_any_numeric ,
  7003.                                   o_off ) ;
  7004.                   temp_num := new_value ( current_formatting_parameters 
  7005.                                           .Paragraph_Indent ,
  7006.                                           -140 , 140 ,
  7007.                                           font_width ) ;
  7008.                   current_formatting_parameters.paragraph_indent   :=temp_num ;
  7009.                   current_formatting_parameters.subsequent_line_ind:=       0 ;
  7010.                   horizontal_control_values_changed ;
  7011.        
  7012.       when indent_neg_command             => 
  7013.                   --  1 Apr 85
  7014.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  7015.                   -- // .cmd off   //
  7016.                   -- // .cmd default //
  7017.                   -- n measured in the current font pitch
  7018.                   -- minimum value is - 140     for  negative 140 characters
  7019.                   -- maximum value is 140       for 140 characters
  7020.                   -- default value is 0         for  off
  7021.                   -- Neg Indent sets - first line indentation, following = 0 
  7022.                   finish_current_text ;
  7023.                   allow_options ( exactly_one ,
  7024.                                   o_any_numeric ,
  7025.                                   o_off ) ;
  7026.                   temp_num := - new_value ( - current_formatting_parameters 
  7027.                                             .Paragraph_Indent ,
  7028.                                             -140 , 140 ,
  7029.                                             font_width ) ;
  7030.                   current_formatting_parameters.paragraph_indent   :=temp_num ;
  7031.                   current_formatting_parameters.subsequent_line_ind:=       0 ;
  7032.                   horizontal_control_values_changed ;
  7033.        
  7034.       when para_indent_command            => 
  7035.                   --  1 Apr 85
  7036.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  7037.                   -- // .cmd off   //
  7038.                   -- // .cmd default //
  7039.                   -- n measured in the current font pitch
  7040.                   -- minimum value is - 140     for  negative 140 characters
  7041.                   -- maximum value is 140       for 140 characters
  7042.                   -- default value is 0         for  off
  7043.                   -- Para Indent sets following indentation, first = 0 
  7044.                   finish_current_text ;
  7045.                   allow_options ( exactly_one ,
  7046.                                   o_any_numeric ,
  7047.                                   o_off ) ;
  7048.                   temp_num := new_value ( current_formatting_parameters 
  7049.                                           .subsequent_line_ind ,
  7050.                                           -140 , 140 ,
  7051.                                           font_width ) ;
  7052.                   current_formatting_parameters.paragraph_indent   :=       0 ;
  7053.                   current_formatting_parameters.subsequent_line_ind:=temp_num ;
  7054.                   horizontal_control_values_changed ;
  7055.        
  7056.       when page_numbering_command         => 
  7057.                   --  1 Apr 85
  7058.                   -- // .cmd off   //  page number off prefix/suffix blank
  7059.                   -- // .cmd on    //  page number display on
  7060.                   -- // .cmd default //sets values to default values, disp. off
  7061.                   -- // .cmd TB LRCA NUM PS
  7062.                   -- DEFAULTS:    Top or Bottom => BOTTOM
  7063.                   --              Left/Right/Ctr=> CENTER
  7064.                   --              Start with    => Page 1
  7065.                   --              Prefix/Suffix => None
  7066.                   --              Show Page Num => Off
  7067.                   do_set_page_number ;
  7068.        
  7069.       when section_page_numbering_command => 
  7070.                   --  1 Apr 85
  7071.                   -- // just like page numbers...
  7072.                   do_set_page_number ( true ) ;
  7073.        
  7074.       when date_dmy_command
  7075.          | date_mdy_command
  7076.          | date_slash_command
  7077.          | date_dash_command 
  7078.          | date_ymd_command               => 
  7079.                   --  2 Apr 85
  7080.                   -- // .cmd   //  
  7081.                   -- // .cmd "text" //
  7082.                   allow_options ( false ,
  7083.                                   o_text_param ) ;
  7084.                   month_out( command ) ;
  7085.      
  7086.       when underscore_command             => -- draw a horizontal line
  7087.                   --  3 Apr 85
  7088.                   -- // .cmd n  //  
  7089.                   -- // .cmd n "text" //
  7090.                   -- n measured in characters
  7091.                   allow_options ( false         ,
  7092.                                   o_abs_numeric ,
  7093.                                   o_text_param  ) ;
  7094.                   temp_num := new_value ( 0 , 1 , 255 , 1 ) ;
  7095.                   -- minimum is 1 , maximum is 255
  7096.                   Input_Line_Length := temp_num      ;
  7097.                   for posn in 1 .. temp_num      loop
  7098.                     Input_Line ( posn ) := extended_character ( 
  7099.                                                 character'pos ( '_' ) ) ;
  7100.                   end loop ;
  7101.                   Input_Line_Contains_Text := true ;
  7102.        
  7103.       when write_command                  => 
  7104.                   --  2 Apr 85
  7105.                   -- // .cmd prompt //
  7106.                   -- moves prompt out to the screen as a prompt for read cmd
  7107.                   allow_options ( exactly_one ,
  7108.                                   o_text_param ) ;
  7109.                   do_write_command ;
  7110.        
  7111.       when read_command                   => 
  7112.                   --  2 Apr 85
  7113.                   -- // .cmd   //  
  7114.                   -- // .cmd text //
  7115.                   -- if "text" is there, it appends it to the read info.
  7116.                   allow_options ( false ,
  7117.                                   o_text_param ) ;
  7118.                   do_read_command ;
  7119.        
  7120.       when new_para_command               => 
  7121.                   --  2 Apr 85
  7122.                   -- // .cmd   //  
  7123.                   allow_options ( false ) ;
  7124.                   finish_current_text ; -- finishes the paragraph
  7125.                   -- and then prepares for a new paragraph
  7126.        
  7127.       when add_command                    => 
  7128.                   --  2 Apr 85
  7129.                   -- // .cmd n  //  
  7130.                   -- n measured in lines
  7131.                   allow_options ( false         ,
  7132.                                   -- used to be exactly_one   ,
  7133.                                   -- but was changed because jennifer uses
  7134.                                   -- .add <cr> to mean .newp....
  7135.                                   o_abs_numeric ) ;
  7136.                   temp_num := new_value ( 0 , 0 , 66 , 1 ) ;
  7137.                   -- min is 0 .. max is 66 lines
  7138.                   finish_current_text ( move_forward_on_page ,
  7139.                                         temp_num             ) ;
  7140.                   -- finishes the paragraph
  7141.                   -- and then prepares for a new paragraph
  7142.                   -- also, moves the after line count to the before line
  7143.      
  7144.       when backward_add_command           => 
  7145.                   --  2 Apr 85
  7146.                   -- // .cmd n  //  
  7147.                   -- n measured in lines
  7148.                   allow_options ( exactly_one   ,
  7149.                                   o_abs_numeric ) ;
  7150.                   temp_num := new_value ( 0 , 0 , 66 , 1 ) ;
  7151.                   -- min is 0 .. max is 66 lines
  7152.                   finish_current_text ( move_backward_on_page,
  7153.                                         temp_num             ) ;
  7154.                   -- finishes the paragraph
  7155.                   -- and then prepares for a new paragraph
  7156.                   -- also, moves the after line count to the before line
  7157.        
  7158.       when tabs_vertical_command          => 
  7159.                   --  2 Apr 85
  7160.                   -- // .cmd n  //  
  7161.                   -- n measured in lines
  7162.                   allow_options ( exactly_one   ,
  7163.                                   o_abs_numeric ) ;
  7164.                   temp_num := new_value ( 0 , 1 , 66 , 1 ) ;
  7165.                   -- min is 1 .. max is 66 lines
  7166.                   finish_current_text ( move_to_absolute_position ,
  7167.                                         temp_num             ) ;
  7168.                   -- finishes current text and then does an absolute move
  7169.        
  7170.       when same_line_command              => 
  7171.                   --  2 Apr 85
  7172.                   -- // .cmd    //
  7173.                   allow_options ( false ) ;
  7174.                   if Current_Formatting_Parameters.Filling_On then
  7175.                     -- output and then stay on this line
  7176.                     finish_current_text ( stay_on_this_line    ) ;
  7177.                     -- finishes current text and then stays here...
  7178.                   else
  7179.                     -- filling off, set for staying here before next line
  7180.                     kind_of_move_before_line          := stay_on_this_line ;
  7181.                     amount_waiting_to_move_vertically_before_line := 0     ;
  7182.                   end if ;
  7183.        
  7184.       when tabs_command                   => 
  7185.                   --  2 Apr 85
  7186.                   -- // .cmd n  // .cmd +n //
  7187.                   -- n measured in the current font pitch
  7188.                   -- if +n, the n is measured from left margin + sub para
  7189.                   -- minimum value is 0         for left edge of page
  7190.                   -- maximum value is 255       for 255th char position
  7191.                   allow_options ( exactly_one ,
  7192.                                   o_any_numeric ) ;
  7193.                   temp_num := new_value ( current_physical_parameters
  7194.                                           .left_margin +
  7195.                                           current_formatting_parameters
  7196.                                           .Left_Indentation ,
  7197.                                           0 , 255 , font_width ) ;
  7198.                   if Current_Formatting_Parameters.Filling_On then
  7199.                     -- output and then stay on this line
  7200.                     finish_current_text ( stay_on_this_line    ) ;
  7201.                     -- finishes current text and then stays here...
  7202.                     just_did_tab_command := true ;
  7203.                     tab_requested_to_position := temp_num ;
  7204.                   else
  7205.                     null ; -- has no meaning if filling is off...
  7206.                   end if ;
  7207.        
  7208.       when comments_command               => 
  7209.                   --  2 Apr 85
  7210.                   -- // .cmd on    //  -- turns comment area on
  7211.                   -- // .cmd off   //  -- turns comment area off
  7212.                   --                   -- however, note that the comment off
  7213.                   --                   -- to on is really handled elsewhere
  7214.                   allow_options ( exactly_one ,
  7215.                                   o_on_off    ) ;
  7216.                   processing_comment_area := ( modifier_one = on_modifier ) ;
  7217.        
  7218.       when else_command                   => 
  7219.                   --  2 Apr 85
  7220.                   -- // .cmd       //  -- if comment on, turns off. 
  7221.                   --                   -- if comment off, turns on.
  7222.                   --                   -- however, note that the comment on
  7223.                   --                   -- to off is really handled elsewhere
  7224.                   allow_options ( false ) ;
  7225.                   processing_comment_area := not processing_comment_area ;
  7226.        
  7227.       when finish_command                 => 
  7228.                   --  2 Apr 85
  7229.                   -- // .cmd       //  -- if comment on, turns off. 
  7230.                   --                   -- however, note that the comment on
  7231.                   --                   -- to off is really handled elsewhere
  7232.                   allow_options ( false ) ;
  7233.                   processing_comment_area := false ;
  7234.        
  7235.       when switch_command                 => 
  7236.                   --  2 Apr 85
  7237.                   -- // .cmd n on //
  7238.                   -- // .cmd n off //
  7239.                   -- // .cmd n toggle //
  7240.                   -- minimum value is 1         for  first switch
  7241.                   -- maximum value is 20        for  last switch
  7242.                   allow_options ( false       ,
  7243.                                   o_on_off    ,
  7244.                                   o_toggle    ,
  7245.                                   o_abs_numeric);
  7246.                   temp_num := new_value ( 0 , 1 , max_switches , 1 ) ;
  7247.                   if modifier_two /= no_modifier then
  7248.                     -- they had two modifiers, and that is not allowed
  7249.                     command_error ( "Invalid Switch Parameters." , true ) ;
  7250.                   end if ;
  7251.                   if modifier_one = toggle_modifier then
  7252.                     switches ( temp_num ) := not switches ( temp_num ) ;
  7253.                   else
  7254.                     switches( temp_num ) := ( modifier_one = on_modifier ) ;
  7255.                   end if ;
  7256.        
  7257.       when ifswitch_command               => 
  7258.                   --  2 Apr 85
  7259.                   -- // .cmd n on //
  7260.                   -- // .cmd n off //
  7261.                   -- minimum value is 1         for  first switch
  7262.                   -- maximum value is 20        for  last switch
  7263.                   allow_options ( false       ,
  7264.                                   o_on_off    ,
  7265.                                   o_abs_numeric);
  7266.                   temp_num := new_value ( 0 , 1 , max_switches , 1 ) ;
  7267.                   if modifier_two /= no_modifier then
  7268.                     -- they had two modifiers, and that is not allowed
  7269.                     command_error ( "Invalid Switch Parameters." , true ) ;
  7270.                   end if ;
  7271.                   processing_comment_area :=
  7272.                         switches( temp_num ) /= ( modifier_one = on_modifier ) ;
  7273.                         -- comment area if switch on and looking for off 
  7274.                         --              or        off and looking for on
  7275.                          
  7276.       when if_command                     =>
  7277.                   --  4 Apr 85
  7278.                   -- // .cmd n = n //
  7279.                   -- processing_comment_area := If_Function ;
  7280.                   null ;
  7281.        
  7282.       when bold_command                   => 
  7283.                   --  2 Apr 85
  7284.                   -- // .cmd on //
  7285.                   -- // .cmd off //
  7286.                   allow_options ( exactly_one ,
  7287.                                   o_on_off    ) ;
  7288.                   set_formatting ( bold ) ;
  7289.        
  7290.       when shadow_printing_command        => 
  7291.                   --  2 Apr 85
  7292.                   -- // .cmd on //
  7293.                   -- // .cmd off //
  7294.                   allow_options ( exactly_one ,
  7295.                                   o_on_off    ) ;
  7296.                   set_formatting ( shadow ) ;
  7297.        
  7298.       when underline_chars_command        => 
  7299.                   --  2 Apr 85
  7300.                   -- // .cmd on //
  7301.                   -- // .cmd off //
  7302.                   allow_options ( exactly_one ,
  7303.                                   o_on_off    ) ;
  7304.                   set_formatting ( underline ) ;
  7305.        
  7306.       when underline_cont_command         => 
  7307.                   --  2 Apr 85
  7308.                   -- // .cmd on //
  7309.                   -- // .cmd off //
  7310.                   allow_options ( exactly_one ,
  7311.                                   o_on_off    ) ;
  7312.                   set_formatting ( underline_continuous ) ;
  7313.        
  7314.       when fancy_print_command            => 
  7315.                   --  2 Apr 85
  7316.                   -- // .cmd on //
  7317.                   -- // .cmd off //
  7318.                   allow_options ( exactly_one ,
  7319.                                   o_on_off    ) ;
  7320.                   set_formatting ( bold ) ;
  7321.                   set_formatting ( shadow ) ;
  7322.                   set_formatting ( underline_continuous ) ;
  7323.        
  7324.       when center_command                 => 
  7325.                   --  2 Apr 85
  7326.                   -- // .cmd on    //  -- turns centering on forever
  7327.                   -- // .cmd off   //  -- turns centering off
  7328.                   -- // .cmd n     //  -- center the next n lines
  7329.                   --                   Note that the on and n parts of the
  7330.                   --                   command cause the program to remember
  7331.                   --                   the settings of the filling and just
  7332.                   --                   commands.  Then, when the n is up or
  7333.                   --                   the off is given, those two items are
  7334.                   --                   reset to their previous settings
  7335.                   -- note that calling fill or justify on turns off center
  7336.                   -- also right justify turns this off...
  7337.                   set_line_modification ( Line_Modification_Type'( Center_Mod),
  7338.                                           True ) ;
  7339.                   -- set line modification to center and use the current
  7340.                   -- parsed command line...
  7341.        
  7342.       when justify_rtmargin_command       => 
  7343.                   --  2 Apr 85
  7344.                   -- // .cmd on    //  -- turns right justification on forever
  7345.                   -- // .cmd off   //  -- turns right justification off
  7346.                   -- // .cmd n     //  -- center the next n lines
  7347.                   --                   Note that the on and n parts of the
  7348.                   --                   command cause the program to remember
  7349.                   --                   the settings of the filling and just
  7350.                   --                   commands.  Then, when the n is up or
  7351.                   --                   the off is given, those two items are
  7352.                   --                   reset to their previous settings
  7353.                   -- note that calling fill or justify on turns off rjust
  7354.                   -- so does center..
  7355.                   set_line_modification ( Right_Justify , True ) ;
  7356.                   -- set line modification to right_justify and use the current
  7357.                   -- parsed command line...
  7358.        
  7359.       when hypen_command                  
  7360.          | dot_lead_command               
  7361.          | forced_space_character_command =>
  7362.                   --  2 Apr 85
  7363.                   -- // .cmd "c"      //  -- "c" signals special function
  7364.                   allow_options ( exactly_one , o_text_param) ;
  7365.                   work_character_command ;
  7366.        
  7367.       when subscript_command              
  7368.          | superscript_command            
  7369.          | underline_foothead_command     
  7370.          | underline_character_command    
  7371.          | ucontinuous_character_command  
  7372.          | bold_character_command         
  7373.          | shadow_character_command       
  7374.          | temporary_font_character_command =>
  7375.                   --  2 Apr 85
  7376.                   -- // .cmd on "c"       //  -- "c" turns special function on 
  7377.                   -- // .cmd off "c"      //  -- "c" turns special function off
  7378.                   -- // .cmd toggle "c"   //  -- "c" changes the setting 
  7379.                   allow_options ( false ,
  7380.                                   o_on_off    ,
  7381.                                   o_toggle    ,
  7382.                                   o_text_param) ;
  7383.                   if length( text_parameters ) = 0 then
  7384.                     command_error ( 
  7385.                             "You must provide a character for this command." ,
  7386.                             true ); 
  7387.                   elsif modifier_two /= no_modifier then
  7388.                     command_error ( "Too many command parameters." , true ) ;
  7389.                   else
  7390.                     work_character_command ;
  7391.                   end if ;
  7392.        
  7393.       when insert_command                 => 
  7394.                   --  2 Apr 85
  7395.                   -- // .cmd filename   //  
  7396.                   -- Include the file named here as though it was typed in
  7397.                   -- .... note that an include file cannot try to include 
  7398.                   -- another file...
  7399.                   do_insert_command ;
  7400.                    
  7401.       when indexfile_command              => 
  7402.                   --  2 Apr 85
  7403.                   -- // .cmd filename   //  
  7404.                   -- Open the file named here as the index output file.
  7405.                   do_indexfile_command ;
  7406.        
  7407.       when index_command                  => 
  7408.                   --  2 Apr 85
  7409.                   -- // .cmd indexinfo  //
  7410.                   allow_options ( exactly_one , o_text_param ) ;
  7411.                   If index_file_is_open then
  7412.                     -- put it away
  7413.                     text_parameters:= text_parameters & " \" & page_to_pstring ;
  7414.                     -- that put a second space at the end...
  7415.                     -- and then the dot leader character & then page number
  7416.                     text_io.put ( index_output_file , ".idx " ) ;
  7417.                     text_io.put_line ( index_output_file ,
  7418.                        text_parameters.data ( 1 .. length(text_parameters) ) ) ;
  7419.                   -- else do nothing...we allow the user to put in index
  7420.                   -- entries for later without specifying a file for them
  7421.                   -- now
  7422.                   end if ;
  7423.                    
  7424.       when footers_command                => 
  7425.                   --  3 Apr 85
  7426.                   -- // .cmd n  // -- n lines of footers
  7427.                   -- n is from 1 .. 66 
  7428.                   process_header_footer_lines ( true , -- this is a head/foot
  7429.                                                 false , -- but not a header
  7430.                         current_document_parameters.Footing_Lines    ,
  7431.                         current_document_parameters.Footing_Height   ,
  7432.                         current_document_parameters.Footing_Pointer  ) ;
  7433.                   reset_vertical_physical_page_limits ;
  7434.                    
  7435.       when footnote_command               => 
  7436.                   --  3 Apr 85
  7437.                   -- // .cmd n  // -- n lines of footnotes
  7438.                   -- n is from 1 .. 66 
  7439.                   process_header_footer_lines ( false , -- not a head/foot
  7440.                                                 false , -- not a header
  7441.                         current_document_parameters.FootNote_Lines    ,
  7442.                         current_document_parameters.FootNote_Height   ,
  7443.                         current_document_parameters.FootNote_Pointer  ) ;
  7444.                   reset_vertical_physical_page_limits ;
  7445.        
  7446.       when headers_command                => 
  7447.                   --  3 Apr 85
  7448.                   -- // .cmd n  // -- n lines of headers
  7449.                   -- n is from 1 .. 66 
  7450.                   process_header_footer_lines ( true , -- this is a head/foot
  7451.                                                 true , -- and is a header
  7452.                         current_document_parameters.Heading_Lines    ,
  7453.                         current_document_parameters.Heading_Height   ,
  7454.                         current_document_parameters.Heading_Pointer  ) ;
  7455.                   reset_vertical_physical_page_limits ;
  7456.                    
  7457.       when head_foot_space_command        => 
  7458.                   --  3 Apr 85
  7459.                   -- // .cmd n  // -- n is points to allocate to each header
  7460.                   --               -- footer and footnote line.
  7461.                   --               -- point height is different for different
  7462.                   --               -- printers.
  7463.                   -- minimum 1 point
  7464.                   -- maximum is number of vertical points per inch
  7465.                   do_set_head_foot_space ;
  7466.        
  7467.       when forward_printing_command       => 
  7468.                   --  3 Apr 85
  7469.                   -- // .cmd on // -- this can force a unidirectional printer
  7470.                   allow_options ( exactly_one , o_on_off ) ;
  7471.                   if modifier_one = off_modifier then
  7472.                     -- error not caught by allow_options
  7473.                     command_error ( 
  7474.                               "Off Parameters not allowed with this command." 
  7475.                               , true );
  7476.                   else
  7477.                     z_forward := true ;
  7478.                   end if ;
  7479.        
  7480.       when justify_numbers_command        => 
  7481.                   --  3 Apr 85
  7482.                   -- // .cmd on // -- turns dot justification on
  7483.                   -- // .cmd off// -- turns dot justification off
  7484.                   allow_options ( exactly_one , o_on_off ) ;
  7485.                   current_formatting_parameters.
  7486.                               Delay_Justification_Till_After_Dots 
  7487.                                         := modifier_one = on_modifier ;
  7488.        
  7489.       when pause_command                  => 
  7490.                   --  3 Apr 85
  7491.                   -- // .cmd // -- pause while printing...
  7492.                   allow_options ( false ) ;
  7493.                   finish_current_text ;
  7494.                   if User_Pause ( "Pause!" , true ) then
  7495.                     raise users_requested_abort ;
  7496.                   end if ;
  7497.        
  7498.       when variable_data_command          => 
  7499.                   --  3 Apr 85
  7500.                   -- // .cmd n   //  -- take and insert the specified variable
  7501.                   -- // .cmd n "text" // -- field.  append "text" if requested
  7502.                   -- minimum n is 1
  7503.                   -- maximum n is 20
  7504.                   allow_options ( false ,
  7505.                                   o_abs_numeric ,
  7506.                                   o_text_param  ) ;
  7507.                   temp_num := new_value( 0, 1, max_user_variables , 1 ) ;
  7508.                   force_into_input_stream ( user_variable_data ( temp_num ) ,
  7509.                                             input_line_contains_text ) ;
  7510.      
  7511.       when user_defined_command           => 
  7512.                   --  3 Apr 85
  7513.                   -- // .cmd   //  -- take and insert the specified variable
  7514.                   -- // .cmd "text" // -- field.  append "text" if requested
  7515.                   -- the n is set by the user_command_number...
  7516.                   allow_options ( false ,
  7517.                                   o_text_param  ) ;
  7518.                   if user_command_number > 0
  7519.                   and then user_command_number <= max_user_variables then
  7520.                     force_into_input_stream( user_variable_data ( 
  7521.                                                 user_command_number ) ,
  7522.                                              input_line_contains_text ) ;
  7523.                   end if ;
  7524.  
  7525.       when prop_spacing_command           => 
  7526.                   --  3 Apr 85
  7527.                   -- // .cmd n   //  -- load that print font
  7528.                   -- minimum n is 1
  7529.                   -- maximum n is 50
  7530.                   allow_options ( false ,
  7531.                                   o_abs_numeric ) ;
  7532.                   temp_num := new_value( 0, 1, 50 , 1 ) ;
  7533.                   if not select_font ( temp_num ) then
  7534.                     command_error ("Invalid Font Number." , true ) ;
  7535.                   else
  7536.                     -- since this is to change permanent font, then we will
  7537.                     -- change the font width
  7538.                     permanent_font := current_font ;
  7539.                     font_width     := current_font.font_width ; 
  7540.                   end if ;
  7541.                    
  7542.       when rclm_command                   => -- Right Column Left Margin 
  7543.                   --  3 Apr 85
  7544.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  7545.                   -- // .cmd off   //
  7546.                   -- n measured in 1/10"
  7547.                   -- minimum value is  0        for  no right margin
  7548.                   -- maximum value is 140       for 14 inches
  7549.                   -- default value is  0        for  off
  7550.                   -- 
  7551.                   -- note that this command just sets up a value in case
  7552.                   -- lcrm is called.  If it is never called, nothing 
  7553.                   -- will happen...
  7554.                   --
  7555.                   allow_options ( exactly_one ,
  7556.                                   o_any_numeric ,
  7557.                                   o_off ) ;
  7558.                   temp_num := new_value ( current_physical_parameters
  7559.                                           .real_center_left  ,
  7560.                                           0 , 140 ,
  7561.                                           printer_points_per_inch / 10 ) ;
  7562.                   current_physical_parameters.real_center_left := temp_num ;
  7563.                    
  7564.       when lcrm_command                   => -- Left Column Right Margin
  7565.                   --  3 Apr 85
  7566.                   -- // .cmd n     //  .cmd +n    //  .cmd -n     // 
  7567.                   -- // .cmd off   //
  7568.                   -- n measured in 1/10"
  7569.                   -- minimum value is  0        for  no left margin
  7570.                   -- maximum value is 140       for 14 inches
  7571.                   -- default value is  0        for  off
  7572.                   finish_current_text ;
  7573.                   allow_options ( exactly_one ,
  7574.                                   o_any_numeric ,
  7575.                                   o_off ) ;
  7576.                   temp_num := new_value ( current_physical_parameters
  7577.                                           .real_center_right ,
  7578.                                           0 , 140 ,
  7579.                                           printer_points_per_inch / 10 ) ;
  7580.                   current_physical_parameters.real_center_right := temp_num ;
  7581.                   current_physical_parameters.right_margin      := temp_num ;
  7582.                   reset_horizontal_physical_page_limits ;
  7583.                    
  7584.       when char_spacing_command 
  7585.          | char_width_command             => 
  7586.                   --  4 Apr 85
  7587.                   -- // .cmd n     //
  7588.                   -- char width command is said in printer points
  7589.                   -- char spacing command is characters per inch
  7590.                   -- for char width  , minimum width is  1 point
  7591.                   --                   maximum width is  1" worth of points
  7592.                   -- for char spacing, minimum cpi is 1 cpi
  7593.                   --                   maximum cpi is number of points in inch
  7594.                   -- depending upon printer, between 120 and 300 cpi
  7595.                   finish_current_text ;
  7596.                   allow_options ( exactly_one ,
  7597.                                   o_abs_numeric ) ;
  7598.                   temp_num := new_value ( 0 , 1 , printer_points_per_inch, 1 );
  7599.                   if command = char_spacing_command then
  7600.                     -- must reverse
  7601.                     temp_num := printer_points_per_inch / temp_num ;
  7602.                   end if ;
  7603.                   set_fixed_font ( temp_num ) ;
  7604.                   reset_horizontal_physical_page_limits ;
  7605.                    
  7606.       when mult_line_spacing_command      
  7607.          | vert_line_spacing_command      =>
  7608.                   --  4 Apr 85
  7609.                   -- // .cmd n     //
  7610.                   -- vert line spacing cmd is said in printer vertical points
  7611.                   -- mult line spacing command is 1/6" increments
  7612.                   -- minimum is 1 point for vert, 1/6" for mult
  7613.                   -- maximum is 1" worth of points for vert , 12 for mult
  7614.                   finish_current_text ;
  7615.                   allow_options ( exactly_one ,
  7616.                                   o_abs_numeric ) ;
  7617.                   if command = mult_line_spacing_command then
  7618.                     temp_num := new_value ( 0 , 1 , 12 , 1 )
  7619.                                         * printer_vertical_per_inch / 6 ;
  7620.                   else
  7621.                     temp_num:= new_value ( 0 , 1 , printer_vertical_per_inch,1);
  7622.                   end if ;
  7623.                   -- get here with absolute points set...
  7624.                   execute_printer_command( set_vmi , temp_num ) ;
  7625.                   reset_vertical_physical_page_limits ;
  7626.                    
  7627.       when fill_command                   => 
  7628.                   --  4 Apr 85
  7629.                   -- // .cmd on    //  -- turns filling on 
  7630.                   -- // .cmd off   //  -- turns filling off
  7631.                   -- note that this turns off right justify and center 
  7632.                   allow_options ( exactly_one ,
  7633.                                   o_on_off      ) ;
  7634.                   set_line_modification ( Nothing , False ) ;
  7635.                   -- turn off center/right justify
  7636.                   finish_current_text ;
  7637.                   Current_Formatting_Parameters.Filling_On 
  7638.                                 := modifier_one = on_modifier ;
  7639.       
  7640.       when justify_margins_command        => 
  7641.                   --  4 Apr 85
  7642.                   -- // .cmd on    //  -- turns justify on 
  7643.                   -- // .cmd off   //  -- turns justify off
  7644.                   -- note that this turns off right justify and center 
  7645.                   allow_options ( exactly_one ,
  7646.                                   o_on_off      ) ;
  7647.                   set_line_modification ( Nothing , False ) ;
  7648.                   -- turn off center/right justify
  7649.                   finish_current_text ;
  7650.                   Current_Formatting_Parameters.Justification_On 
  7651.                                 := modifier_one = on_modifier ;
  7652.        
  7653.       when end_page_command               => 
  7654.                   --  4 Apr 85
  7655.                   -- // .cmd // 
  7656.                   allow_options ( false ) ;
  7657.                   finish_current_text ;
  7658.                   end_a_page ;
  7659.                   reset_vertical_physical_page_limits ;
  7660.                   kind_of_move_before_line          := move_forward_on_page  ;
  7661.                   amount_waiting_to_move_vertically_before_line := 0         ;
  7662.                   kind_of_move_after_line           := move_forward_on_page  ;
  7663.                   amount_waiting_to_move_vertically_after_line  := 0         ;
  7664.        
  7665.       when envelope_feed_command          =>            -- NOT IMPLEMENTED
  7666.                   --  4 Apr 85
  7667.                   -- // .cmd //  
  7668.                   allow_options ( false ) ;
  7669.                   finish_current_text ;
  7670.                   -- pagemin := 0 ; --allow the envelope
  7671.                   -- pagenum := 0 ;
  7672.        
  7673.       when line_save_command              => 
  7674.                   -- 26 Jul 85
  7675.                   -- // .cmd n    //  -- save n lines at end of page...
  7676.                   finish_current_text ;
  7677.                   allow_options ( exactly_one ,
  7678.                                   o_abs_numeric ) ;
  7679.                   temp_num := new_value ( 0 , 1 , 66 , 1 ) ;
  7680.                   if printer_vertical_position 
  7681.                        + amount_waiting_to_move_vertically_before_line 
  7682.                        + current_vertical_motion_index * temp_num 
  7683.                            > Vertical_Page_Limit then
  7684.                     -- new page...
  7685.                     end_a_page ;
  7686.                     -- and skip any vertical requested area...
  7687.                     reset_vertical_physical_page_limits ;
  7688.                     start_a_page ;
  7689.                   end if ;
  7690.         
  7691.       when printer_control_command        => 
  7692.                   --  4 Apr 85
  7693.                   -- // .cmd //  -- turns on for dumb printer ...
  7694.                   -- Note that the user has to take care of font himself...
  7695.                   if current_environment.ot_format = ot_fancy then
  7696.                     printer_accessories := none ;
  7697.                     change_printer( z_pdumb ) ;
  7698.                     permanent_printer := z_printer ;
  7699.                     current_environment.ot_format := ot_plain ;
  7700.                     file_out ( ascii.cr ) ;
  7701.                   end if ;
  7702.        
  7703.       when ribbon_color_command           =>   
  7704.                   --  4 Apr 85
  7705.                   -- // .cmd on    //  -- turns red ribbon on
  7706.                   -- // .cmd off   //  -- turns red ribbon off
  7707.                   if modifier_one = on_modifier then
  7708.                     execute_printer_command( set_red_ribbon ) ;
  7709.                   else
  7710.                     execute_printer_command( set_black_ribbon ) ;
  7711.                   end if ;
  7712.        
  7713.       when illegal_command                => 
  7714.                   command_error ( "Unrecognized Formatter Command." , false );
  7715.        
  7716.     end case ;
  7717.      
  7718.     Commands_Were_Processed_Just_Now := True ;
  7719.      
  7720.     if input_line_contains_text then
  7721.       fix_up_line ;
  7722.     end if ;
  7723.     return_input_line_contains_text := input_line_contains_text ;
  7724.   exception
  7725.     when bad_user_command => return_input_line_contains_text := false ;
  7726.                              -- and return without processing command line
  7727.   end options ;
  7728.  
  7729.     procedure initialize_printer_commands_for_a_new_document     is
  7730.     begin -- initialize_printer_commands_for_a_new_document
  7731.       Filling_output_line.all           := blank_output_line    ;
  7732.       Filling_Trailing_Spaces           := 0                    ;
  7733.       reset_vertical_physical_page_limits ;
  7734.       reset_horizontal_physical_page_limits ;
  7735.       horizontal_control_values_changed ;
  7736.     end initialize_printer_commands_for_a_new_document ;
  7737.    
  7738.     procedure finish_printer_commands_for_an_old_document     is
  7739.     begin -- finish_printer_commands_for_an_old_document
  7740.       null ;
  7741.     end finish_printer_commands_for_an_old_document ;
  7742.    
  7743.     procedure close_printer_commands is
  7744.     begin -- close_printer_commands 
  7745.       null ;
  7746.     end close_printer_commands ;
  7747.      
  7748.   begin -- printer_commands 
  7749.     Filling_output_line               := new output_line_type ;
  7750.     initialize_printer_commands_globally ;
  7751.   end printer_commands ;
  7752.    
  7753.   --$$$- PRNTCMD 
  7754.  
  7755. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7756. --prntwork
  7757. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7758.  
  7759.   --$$$+ PRNTWORK
  7760.   
  7761.   --
  7762.   -- File 0xx
  7763.   --
  7764.   -- Formatter Written By Robert S. Cymbalski
  7765.   --                      Science Applications International Corporation
  7766.   --                      Energy Systems Group
  7767.   --                      Ada Software Development Project Team
  7768.   --                      2280 U.S. Highway 19 North, Suite 120
  7769.   --                      Clearwater, Florida  33575
  7770.   --
  7771.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  7772.   --
  7773.     
  7774.   with text_io         ;
  7775.    
  7776.   with string_library  ;
  7777.   use  string_library  ;
  7778.     
  7779.   with crt_windows     ;
  7780.   use  crt_windows     ;
  7781.     
  7782.   with Wordp_Globals   ;
  7783.   use  Wordp_Globals   ;
  7784.   
  7785.   with printer_globals ;
  7786.   use  printer_globals ;
  7787.      
  7788.   with name_tree       ;
  7789.   use  name_tree       ;
  7790.    
  7791.   with printf          ;
  7792.   use  printf          ;
  7793.     
  7794.   with print_in_to_out ;
  7795.   use  print_in_to_out ;
  7796.    
  7797.   with print_out       ;
  7798.   use  print_out       ;
  7799.    
  7800.   with printer_misc    ;
  7801.   use  printer_misc    ;
  7802.    
  7803.   with printer_commands;
  7804.   use  printer_commands;
  7805.    
  7806.   Package PRINT_WORK is
  7807.    
  7808.     work_fatal_error_abort : exception ;
  7809.      
  7810.     procedure initialize_variable_data_file ;
  7811.       
  7812.     procedure initialize_for_new_data ( ok : out boolean ) ;
  7813.       
  7814.     procedure print_a_single_document ;
  7815.       
  7816.     procedure end_output ( printout_aborted_by_user_intervention : boolean ) ;
  7817.    
  7818.     procedure end_an_entire_document ;
  7819.      
  7820.     procedure close_print_work ;
  7821.      
  7822.   end print_work ;
  7823.       
  7824.   package body print_work is
  7825.       
  7826.     filling_trailing_spaces_are_underlined : boolean ;
  7827.      
  7828.     dot_set : array ( extended_character ) of boolean ;
  7829.      
  7830.     first_line_of_filled_paragraph         : boolean ;
  7831.      
  7832.     erased_it : boolean := false ;
  7833.     last_line : integer :=     0 ;
  7834.      
  7835.     procedure deb ( s : string ; info : integer := 0 ) is
  7836.     begin -- deb
  7837.       if ( s = "PAUSE" ) or ( s = "pause" ) then
  7838.         -- we must pause ...
  7839.         if User_Pause ( "Pause!" , true ) then
  7840.           raise users_requested_abort ;
  7841.         end if ;
  7842.         erased_it := true ;
  7843.         clear_window( master_window ) ;
  7844.         clear_prompt( master_window ) ;
  7845.         last_line  := 1 ;
  7846.       else
  7847.         if not erased_it then
  7848.           erased_it := true ;
  7849.           clear_window( master_window ) ;
  7850.           clear_prompt( master_window ) ;
  7851.           last_line  := 1 ;
  7852.         elsif ( last_line = 20 ) then
  7853.           -- we must pause ...
  7854.           if User_Pause ( "Pause!" , true ) then
  7855.             raise users_requested_abort ;
  7856.           end if ;
  7857.           erased_it := false ;
  7858.         end if ;
  7859.         -- here ready to go to work
  7860.         last_line := last_line + 1 ;
  7861.         goto_line_column ( master_window , last_line , 2 ) ;
  7862.         put ( s ) ;
  7863.         if s'length < 30 then
  7864.           for posn in s'length + 1 .. 30 loop
  7865.             put ( ' ' ) ;
  7866.           end loop ;
  7867.         end if ;
  7868.         put ( "  " ) ;
  7869.         put ( info , 5 ) ;
  7870.       end if ;
  7871.     end deb ;
  7872.      
  7873.     procedure global_initialize_print_work is
  7874.      
  7875.       function e ( c : character ) return extended_character is
  7876.       begin -- e
  7877.         return extended_character ( character'pos( c ) ) ;
  7878.       end e ;
  7879.        
  7880.     begin -- global_initialize_print_work 
  7881.       for e_c in extended_character'first .. extended_character'last loop
  7882.         dot_set ( e_c ) := false ;
  7883.       end loop ;
  7884.       dot_set ( e ( '.' ) ) := true ;
  7885.       dot_set ( e ( ':' ) ) := true ;
  7886.       dot_set ( e ( '-' ) ) := true ;
  7887.       dot_set ( e ( ')' ) ) := true ;
  7888.       dot_set ( e ( 'o' ) ) := true ;
  7889.       dot_set ( e ( 'O' ) ) := true ;
  7890.     end global_initialize_print_work ;
  7891.      
  7892.     procedure initialize_variable_data_file is
  7893.     begin -- initialize_variable_data_file 
  7894.       -- first, make the variable command a valid command....
  7895.       insert_name ( "variable_data_insertion" ,
  7896.                     variable_data_command     , 
  7897.                     000 , command_tree      ) ;
  7898.       -- then, open the file....
  7899.       -- it is already opened by the goodname routine...
  7900.       -- ok then, we are ready for work.....
  7901.     end ;
  7902.       
  7903.     procedure initialize_for_new_data ( ok : out boolean ) is
  7904.       -- read in the next record's data....
  7905.       -- separated by .NEW
  7906.       -- ended with .END
  7907.       -- cannot read in lines starting with '?'
  7908.       new_command : string ( 1 .. 3 ) ;
  7909.       old_read    : input_file_type := where_to_read ;
  7910.       var_numb    : integer ;
  7911.       new_data    : pstring ;
  7912.       eof         : boolean ;
  7913.      
  7914.       procedure map_up ( s : in out string ) is
  7915.       begin -- map_up 
  7916.         for posn in 1 .. s'length loop
  7917.           s(posn) := map_up ( s(posn) ) ;
  7918.         end loop ;
  7919.       end map_up ;
  7920.        
  7921.     begin
  7922.       -- clear old data
  7923.       for ln in 1 .. max_user_variables loop
  7924.         set_length ( user_variable_data ( ln ) , 0 ) ;
  7925.       end loop ;
  7926.       -- select correct input file
  7927.       select_for_read ( variable_input_file ) ;
  7928.       var_numb := 0 ;
  7929.       loop
  7930.         read_next_line ( new_data , eof ) ;
  7931.       exit when eof 
  7932.       or else var_numb = max_user_variables ;
  7933.         -- meaning if they have max_var lines of data, we read in that many
  7934.         -- lines and then throw away the following line no matter what..
  7935.         if length ( new_data ) > 0 then
  7936.           if new_data.data(1) = '?' then
  7937.             -- this throws away environment lines...
  7938.             null ; -- nothing to do...
  7939.           else
  7940.             if new_data.data(1) = '.'
  7941.             and then length ( new_data ) >= 4 then
  7942.               new_command := new_data.data( 1 .. 3 ) ;
  7943.               map_up ( new_command ) ;
  7944.             else 
  7945.               new_command := "   " ;
  7946.             end if ;
  7947.         exit when new_command = "NEW" or else new_command = "END" ;
  7948.             -- get here with real data...
  7949.             -- since the variable info is a standard pstring and
  7950.             -- the new_data is a standard pstring, we don't have to
  7951.             -- check any constraints before moving over...
  7952.             var_numb := var_numb + 1 ;
  7953.             user_variable_data ( var_numb ) := new_data ;
  7954.           end if ;
  7955.         else
  7956.           var_numb := var_numb + 1 ;
  7957.           -- blank line is already set
  7958.         end if ;
  7959.       end loop ;
  7960.       ok := ( var_numb > 0 ) ; -- meaning we had at least one line of data
  7961.       -- set things back to how they used to be...
  7962.       select_for_read ( old_read ) ;
  7963.     end initialize_for_new_data ;
  7964.       
  7965.     procedure print_a_single_document is
  7966.       Input_Line_Contains_Text  : boolean   ;
  7967.      
  7968.       procedure initialize_print_work_for_a_new_document is
  7969.         successfull : boolean ;
  7970.        
  7971.         procedure do_font ( new_font_number : font_number ) is
  7972.           -- prepare the program and the output device for the selected font
  7973.         begin -- do_font
  7974.           execute_printer_command( set_font_number , new_font_number ) ;
  7975.           if select_font( new_font_number ) then
  7976.             -- ready to work it
  7977.             permanent_font := current_font ;
  7978.             temporary_font := current_font ;
  7979.             font_width     := current_font.font_width ;
  7980.             -- following set in select font...
  7981.             -- space_width    := current_font.width ( extended_space ) ;
  7982.             -- half_space_width := space_width / 2 ;
  7983.           else
  7984.             error( " Requested Font # " & int_to_str( new_font_number )
  7985.                              & " is not available." , not_fatal_error ,
  7986.                              operator_wait , short_beep ) ;
  7987.             raise work_fatal_error_abort ;
  7988.           end if ;
  7989.         end do_font ;
  7990.          
  7991.       begin -- initialize_print_work_for_a_new_document
  7992.         -- execute_printer_command( printer_reset ); -- Get printer ready for OT
  7993.         -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts
  7994.         -- Default_Font is set by printer_globals_initialize 
  7995.         if current_environment.where_to = to_screen 
  7996.         or else current_environment.ot_format = ot_plain then
  7997.           -- First, PrntGlob public items
  7998.           printer_accessories := none ;
  7999.           change_printer( z_pdumb ) ;
  8000.           permanent_printer := z_printer ;
  8001.           -- no fancy font work...
  8002.           do_font ( 1 ) ; 
  8003.         elsif current_environment.font_to_use = 0 then
  8004.           -- First, PrntGlob public items
  8005.           printer_accessories := current_environment.printer_accessories ;
  8006.           change_printer( current_environment.printer_brand ) ;
  8007.           permanent_printer := z_printer ;
  8008.           -- they asked for the default font.  And we have a different 
  8009.           -- default depending upon the printer...
  8010.           case current_environment.printer_brand is
  8011.             when z_hp_laser_printer     => do_font( 12 ) ;
  8012.             when z_cent737              => do_font(  6 ) ;
  8013.             when others                 => do_font(  1 ) ;
  8014.           end case ;
  8015.         else
  8016.           -- First, PrntGlob public items
  8017.           printer_accessories := current_environment.printer_accessories ;
  8018.           change_printer( current_environment.printer_brand ) ;
  8019.           permanent_printer := z_printer ;
  8020.           -- they specified a font.... and it is their responsibility to
  8021.           -- make sure that that font is legal on their printer...
  8022.           do_font ( current_environment.font_to_use ) ;
  8023.         end if ;
  8024.         -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts -- Fonts
  8025.         -- Physical_Page_Number    := 1 ; -- in PrntGlob
  8026.         -- Physical_Input_Lines    := 0 ; -- in PrntGlob
  8027.         -- Physical_Output_Lines   := 0 ; -- in PrntGlob
  8028.         -- Now, make sure that we are prepared to correctly read the main 
  8029.         -- input file.
  8030.         select_for_read( main_input_file ) ;
  8031.         -- open_for_read ( main_input_file , main_in_file_name , successfull ) ;
  8032.         -- above open for read done inside prntmain..
  8033.         -- ready to continue...
  8034.         -- Now, items which are defined in PrntOut...
  8035.         -- Horizontal Information 
  8036.         Current_Physical_Parameters.Paper_Width        :=
  8037.                   ( Current_Font.Horizontal_Points_Per_Inch / 2 ) * 17 ; -- 8.5"
  8038.         Current_Physical_Parameters.Left_Margin        :=
  8039.                     Current_Font.Horizontal_Points_Per_Inch ;
  8040.         Current_Physical_Parameters.Right_Margin       :=
  8041.                     Current_Font.Horizontal_Points_Per_Inch ;
  8042.         Current_Physical_Parameters.Binding_Edge       := 0 ;
  8043.         Current_Physical_Parameters.Printing_Left_Side := True ;
  8044.         Current_Physical_Parameters.real_center_right  := 0 ;
  8045.         Current_Physical_Parameters.real_center_left   := 0 ;
  8046.         Current_Physical_Parameters.real_right         :=
  8047.                     Current_Font.Horizontal_Points_Per_Inch ;
  8048.         Current_Physical_Parameters.real_left          :=
  8049.                     Current_Font.Horizontal_Points_Per_Inch ;
  8050.         -- Vertical Information
  8051.         Current_Physical_Parameters.Paper_Length       :=
  8052.                     Current_Font.Vertical_Points_Per_Inch * 11 ; -- 11"
  8053.         Current_Physical_Parameters.Top_Margin         :=
  8054.                     Current_Font.Vertical_Points_Per_Inch ; -- 1"
  8055.         Current_Physical_Parameters.Bottom_Margin      := 
  8056.                     Current_Font.Vertical_Points_Per_Inch ; -- 1"
  8057.         -- Page Numbering Information
  8058.         Current_Document_Parameters.Page_Numbering_On  := False ;
  8059.         Current_Document_Parameters.Current_Page_Number:=     1 ;
  8060.         Current_Document_Parameters.Section_Numbering_On := False ;
  8061.         Current_Document_Parameters.Current_Section_Num:=     1 ;
  8062.         Current_Document_Parameters.Number_Page_At_Top := False ;
  8063.         Current_Document_Parameters.Page_Number_Goes   := Center;
  8064.         Current_Document_Parameters.Page_Prefix_Suffix := Blank_Line ;
  8065.         set_length( Current_Document_Parameters.Page_Prefix_Suffix , 1 ) ;
  8066.         Current_Document_Parameters.Page_Prefix_Suffix.data(1) := '$' ;
  8067.         Current_Document_Parameters.Page_Heading_Footing_VMI := 
  8068.                     Current_Font.Vertical_Points_Per_Inch / 6 ; -- 6 lines/inch
  8069.         -- Heading Information
  8070.         Current_Document_Parameters.Heading_Lines      := 0 ;
  8071.         Current_Document_Parameters.Heading_Height     := 0 ;
  8072.         Current_Document_Parameters.Heading_Pointer    := null ;
  8073.         -- Footing Information
  8074.         Current_Document_Parameters.Footing_Lines      := 0 ;
  8075.         Current_Document_Parameters.Footing_Height     := 0 ;
  8076.         Current_Document_Parameters.Footing_Pointer    := null ;
  8077.         -- Foot Note Information
  8078.         Current_Document_Parameters.FootNote_Lines     := 0 ;
  8079.         Current_Document_Parameters.FootNote_Height    := 0 ;
  8080.         Current_Document_Parameters.FootNote_Pointer   := null ;
  8081.         --
  8082.         need_to_start_page         := True   ;
  8083.         Output_Permitted           := Current_Environment
  8084.                                                .First_Page_To_Print <= 1 ;
  8085.         In_Header_Or_Footer        := False ;
  8086.         Current_Formatting_Parameters.Left_Indentation   := 0 ;
  8087.         Current_Formatting_Parameters.Right_Indentation  := 0 ;
  8088.         Current_Formatting_Parameters.Paragraph_Indent   := 0 ;
  8089.         Current_Formatting_Parameters.Subsequent_Line_Ind:= 0 ;
  8090.         Current_Formatting_Parameters.Filling_On         := False   ;
  8091.         Current_Formatting_Parameters.Justification_On   := False   ;
  8092.         Current_Formatting_Parameters.Fill_Before_Special:= False   ;
  8093.         Current_Formatting_Parameters.Just_Before_Special:= False   ;
  8094.         Current_Formatting_Parameters.Delay_Justification_Till_After_Dots 
  8095.                                                          := False   ;
  8096.         Current_Formatting_Parameters.Line_Modification  := Nothing ;
  8097.         Current_Formatting_Parameters.Modification_Status:= Off     ;
  8098.         Current_Formatting_Parameters.Modify_To_Do       := 0 ;
  8099.         Current_Formatting_Parameters.Permanent_Character_Changes 
  8100.                         := No_Character_Changes ;
  8101.         Current_Formatting_Parameters.Temporary_Character_Changes 
  8102.                         := No_Character_Changes ;
  8103.         Current_Formatting_Parameters.Current_Character_Changes   
  8104.                         := No_Character_Changes ;
  8105.         -- Now, special work for interpreting characters...
  8106.         -- Clear to illegal
  8107.         for ext_char in extended_character'first .. extended_character'last loop
  8108.           char_types ( ext_char ) := illegal_character ;
  8109.         end loop ;
  8110.         -- Set Text Characters
  8111.         for ext_char in extended_space .. extended_character (
  8112.                                 character'pos( '~' ) ) loop
  8113.           char_types ( ext_char ) := Text_Character ;
  8114.         end loop ;
  8115.         -- Now, recognize special characters...
  8116.         for a_char in a_char_type'first .. a_char_type'last loop
  8117.           if default_characters_array ( a_char ) /= extended_nul then
  8118.             -- must change it...
  8119.             char_types ( default_characters_array ( a_char ) ) := a_char ;
  8120.           end if ;
  8121.         end loop ;
  8122.         Current_Characters_Array := Default_Characters_Array ;
  8123.         character_tab_positions  := cleared_bool ;
  8124.         -- PrintF Initialization....
  8125.         Binding_Edge_Amount := 0 ;
  8126.         -- Now, ACTUAL PHYSICAL INITIALIZATION!!!!!!
  8127.         -- and, note thate even though we call print functions with all types
  8128.         --      of parameters, only those which pertain to the current output
  8129.         --      device are executed.....
  8130.         execute_printer_command( set_hmi                ,
  8131.                     Current_Font.Horizontal_Points_Per_Inch / 10 ) ;
  8132.                     -- 10 characters per inch
  8133.         execute_printer_command( set_vmi                ,
  8134.                     Current_Font.Vertical_Points_Per_Inch   /  6 ) ;
  8135.                     -- 6 lines per inch
  8136.         execute_printer_command( set_black_ribbon       ) ;
  8137.         execute_printer_command( set_print_forward      ) ;
  8138.         execute_printer_command( set_form_length        ,
  8139.                     Current_Physical_Parameters.Paper_Length     ) ;
  8140.       end initialize_print_work_for_a_new_document ;
  8141.      
  8142.       Procedure Get_Line is
  8143.         bb                        : boolean   ;
  8144.         cc                        : character ;
  8145.       begin -- get_line 
  8146.         commands_were_processed_just_now := false ;
  8147.         Input_Line_Contains_Text         := false ;
  8148.         loop 
  8149.           if end_of_main_input_file then
  8150.             if ready_to_stop then
  8151.               execute_printer_command(end_last_page) ;
  8152.               return ;
  8153.             else
  8154.               force_into_input_stream( string_to_pstring ( ".endp " ) , bb ) ;
  8155.               ready_to_stop := true ;
  8156.             end if ;
  8157.           else
  8158.             load_input_line(Current_Formatting_Parameters.Filling_On);
  8159.             if Input_Line_Length = 0 then
  8160.               Input_Line_Length := 1 ;
  8161.               Input_Line(1) := extended_space ;
  8162.             end if ;
  8163.             if end_of_main_input_file then  -- this is for blank char last line
  8164.               Input_Line_Contains_Text := false ;
  8165.               for posn in 1 .. Input_Line_Length loop
  8166.                 Input_Line_Contains_Text := ( Input_Line_Contains_Text  
  8167.                                      or (Input_Line(posn) /= extended_space )) ;
  8168.               end loop ;
  8169.               if not Input_Line_Contains_Text 
  8170.               or else processing_comment_area then
  8171.                 force_into_input_stream( string_to_pstring ( ".endp " ) , bb ) ;
  8172.                 ready_to_stop := true ;
  8173.               end if ;
  8174.               Input_Line_Contains_Text := false ;
  8175.               processing_comment_area  := false ;
  8176.             end if ;
  8177.             -- critical...........switches.....
  8178.             if processing_comment_area then 
  8179.               if input_line ( 1 ) = extended_character(character'pos('.')) then
  8180.                 -- possibly a command to reverse it...
  8181.                 -- we need to know the first character of the commands
  8182.                 -- which can affect this
  8183.                 cc := map_up( character'val( Input_Line(2) ) ) ;
  8184.                 if ( cc = 'C' ) or ( cc = 'E' ) or ( cc = 'F' ) then
  8185.                   parse_input_command_line ; -- to find out real meanings 
  8186.                   case command is
  8187.                     when comments_command => processing_comment_area
  8188.                                              :=not (modifier_one = on_modifier);
  8189.                     when else_command     => processing_comment_area := false ;
  8190.                     when finish_command   => processing_comment_area := false ;
  8191.                     when others           => null ; -- doesn't matter what it is
  8192.                   end case ;
  8193.                 end if ;
  8194.               -- else skip this line....
  8195.               end if ;
  8196.             else
  8197.               if Input_Line(1) = extended_character(character'pos('.')) then
  8198.                 options( Input_Line_Contains_Text ) ;
  8199.               else
  8200.                 Input_Line_Contains_Text := ( Input_Line(1) /= 
  8201.                                  extended_character ( character'pos( '?' ) ) ) ;
  8202.               end if ;
  8203.             end if ;
  8204.           end if ;
  8205.         exit when Input_Line_Contains_Text ;
  8206.         end loop ;
  8207.       end get_line ;
  8208.      
  8209.       procedure add_this_line_to_paragraph is
  8210.         -- we have an input line and filling is on
  8211.         --
  8212.         -- Important variables
  8213.         --
  8214.         -- Paragraph & Shape Variables
  8215.         --
  8216.         --      text_waiting_inside_filled_paragraph : boolean
  8217.         --      tab_requested_to_position            : horizontal_measurement
  8218.         --      just_did_tab_command                 : boolean
  8219.         --      rightmost_text_position              : horizontal_measurement
  8220.         --      leftmost_para_text_position          : horizontal_measurement
  8221.         --      leftmost_text_position               : horizontal_measurement
  8222.         --      Current_Formatting_Parameters.Justification_On : boolean
  8223.         --      Current_formatting_parameters.
  8224.         --                      Delay_Justification_Till_After_Dots : boolean
  8225.         -- 
  8226.         -- New Line Variables
  8227.         --
  8228.         --      waiting_output_line                  : output_line_pointer
  8229.         --      waiting_output_invalid_breaks        : boolean_array
  8230.         --
  8231.         -- Filled Line Variables
  8232.         --
  8233.         --      filling_output_line                  : output_line_pointer
  8234.         --      Filling_Trailing_Spaces              : Integer
  8235.         --
  8236.         -- Important Routines
  8237.         --
  8238.         --      tidy_up_and_output_filled_line
  8239.         --
  8240.         ---------------------------------------------------------------------
  8241.         --
  8242.         --      The goal of this routine is to move as many full words over
  8243.         -- from the waiting output line into filling_output_line.  The only
  8244.         -- place the line can be broken is at posn 1 or else a character
  8245.         -- which follows a space which did not have the invalid break value
  8246.         -- set.
  8247.         --
  8248.         ---------------------------------------------------------------------
  8249.         --
  8250.         line_start_position             : output_line_index        := 1 ;
  8251.                                          -- Next Char to move over.
  8252.         last_successfull_position       : output_line_index        := 0 ;
  8253.                                          -- The last character with trailing
  8254.                                          -- spaces which was moved over for
  8255.                                          -- output was this position
  8256.         last_successfull_length         : horizontal_measurement   := 0 ;
  8257.                                          -- length of that area so far
  8258.         ending_position_so_far          : output_line_index        := 0 ;
  8259.                                          -- The last printable character moved
  8260.                                          -- over.
  8261.         Ending_Position_Length          : horizontal_measurement   := 0 ;
  8262.                                          -- no points long yet for ending posn
  8263.         work_position                   : output_line_index        := 0 ;
  8264.                                          -- position to work on now
  8265.         Work_Position_Length            : horizontal_measurement   := 0 ;
  8266.                                          -- same for working position
  8267.         work_without_space_position     : output_line_index        := 0 ;
  8268.         work_without_space_length       : horizontal_measurement   := 0 ;
  8269.         last_char_breakable_space       : boolean                  := false ;
  8270.                                              -- last char not a space for break
  8271.         room_in_filling_line            : horizontal_measurement        ;
  8272.         c                               : extended_character            ;
  8273.         w                               : horizontal_measurement        ;
  8274.         number_of_words                 : integer                  := 0 ;
  8275.         waiting_width                   : horizontal_measurement        ;
  8276.         temporary_waiting_filling_spaces : integer                      ;
  8277.          
  8278.         procedure prepare_for_adding_line is
  8279.           c                               : extended_character            ;
  8280.           w                               : horizontal_measurement        ;
  8281.           position                        : output_line_index             ;
  8282.           added_width                     : horizontal_measurement        ;
  8283.         begin -- prepare_for_adding_line
  8284.           -- need to append the trailing space(s)
  8285.           c := extended_space ;
  8286.           w := current_font.width ( extended_space ) ;
  8287.           position := filling_output_line.character_count + 1 ;
  8288.           added_width := 0 ;
  8289.           loop
  8290.             filling_output_line.the_character ( position ) := c ;
  8291.             filling_output_line.the_width     ( position ) := w ;
  8292.             filling_output_line.font_number   ( position ) :=
  8293.                         filling_output_line.font_number   ( position - 1 ) ;
  8294.             if filling_output_line.special_options then
  8295.               filling_output_line.underline     ( position ) :=
  8296.                         filling_trailing_spaces_are_underlined ;
  8297.               filling_output_line.sub_or_supers ( position ) :=
  8298.                         filling_output_line.sub_or_supers ( position - 1 ) ;
  8299.             end if ;
  8300.             added_width := added_width + w ;
  8301.             position := position + 1 ;
  8302.             filling_trailing_spaces := filling_trailing_spaces - 1 ;
  8303.           exit when filling_trailing_spaces <= 0 ;
  8304.           end loop ;
  8305.           filling_output_line.character_count := position - 1 ;
  8306.           filling_output_line.stop_position := 
  8307.                       filling_output_line.stop_position + added_width ;
  8308.           if not current_formatting_parameters.justification_on then
  8309.             filling_output_line.justify_to := 
  8310.                       filling_output_line.stop_position ;
  8311.           end if ;
  8312.         end prepare_for_adding_line ;
  8313.          
  8314.         function look_for_dots return output_line_index is
  8315.           place : output_line_index := 1 ;
  8316.           cc    : character     ;
  8317.           good  : boolean       ;
  8318.         begin -- look_for_dots
  8319.           -- return the place where the first word starts following a
  8320.           -- line starting with a dot type word.  Else, return 1
  8321.           while ( place < filling_output_line.character_count )
  8322.           and then ( filling_output_line.the_character ( place ) 
  8323.                                                         /= extended_space ) loop
  8324.             place := place + 1;
  8325.           end loop ;
  8326.           place := place - 1 ;
  8327.           if place = 0 then
  8328.             return 1 ; -- blank line
  8329.           elsif not dot_set ( filling_output_line.the_character ( place ) ) then
  8330.             return 1 ; -- not ending in dot_set
  8331.           else
  8332.             -- ended in correct character
  8333.             cc := character'val ( filling_output_line.the_character ( place ) );
  8334.             if ( cc = 'o' ) or ( cc = 'O' ) then
  8335.               good := place = 1 ;  -- only dot if single character...
  8336.             else
  8337.               good := place <= 5 ; -- only up to 5 characters before dot char
  8338.             end if ;
  8339.             if not good then
  8340.               return 1 ; -- no dots...
  8341.             else
  8342.               -- must refigure it out
  8343.               filling_output_line.wordspace_count := 
  8344.                                 filling_output_line.wordspace_count - 1 ;
  8345.               place := place + 2 ; -- one for current char, one for space
  8346.               while ( place < filling_output_line.character_count )
  8347.               and then ( filling_output_line.the_character ( place ) 
  8348.                                                          = extended_space ) loop
  8349.                 place := place + 1;
  8350.               end loop ;
  8351.               return place ; -- that is where we will now start justification
  8352.             end if ;
  8353.           end if ;
  8354.         end look_for_dots ;
  8355.          
  8356.         procedure Move_Over_Current_Text is
  8357.           fill_start : output_line_index ;
  8358.           work_start : output_line_index ;
  8359.           work_stop  : output_line_index ;
  8360.           old_font   : font_number       ;
  8361.           font_numb  : font_number       ;
  8362.         begin -- Move_Over_Current_Text 
  8363.           if ending_position_so_far < 1 then
  8364.             -- we are forcing out an old line which is just waiting for output
  8365.             return ;
  8366.           end if ;
  8367.           -- note, if it is a single word, we let it fit anyway!
  8368.           -- move line_start_position .. work_without_space_position over
  8369.           -- starting at filling_output_line.character_count + 1
  8370.           --
  8371.           -- First, move over the current text which might be waiting
  8372.           fill_start := filling_output_line.character_count + 1 ;
  8373.           work_start := line_start_position                     ;
  8374.           work_stop  := ending_position_so_far                  ;
  8375.           -- following to be used to set if any font changes
  8376.           if fill_start = 1 then
  8377.             -- new line
  8378.             old_font := waiting_output_line.font_number ( work_start ) ;
  8379.           else
  8380.             old_font := filling_output_line.font_number ( fill_start - 1 ) ;
  8381.           end if ;
  8382.           loop
  8383.           exit when work_start > work_stop ;
  8384.             filling_output_line.the_character ( fill_start )
  8385.                            := waiting_output_line.the_character ( work_start ) ;
  8386.             filling_output_line.the_width     ( fill_start )
  8387.                            := waiting_output_line.the_width     ( work_start ) ;
  8388.             font_numb      := waiting_output_line.font_number   ( work_start ) ;
  8389.             filling_output_line.font_number   ( fill_start ) := font_numb      ;
  8390.             if font_numb /= old_font then
  8391.               filling_output_line.font_changes := true ;
  8392.               -- once set true we don't care, so don't set old_font to
  8393.               -- anything else...
  8394.             end if ;
  8395.             if waiting_output_line.special_options then
  8396.               filling_output_line.special_options := true ;
  8397.               -- note that this might set special options when we really don't
  8398.               -- have any, but this is just to save processing time, and we
  8399.               -- will save the most time by setting it no matter what.
  8400.               filling_output_line.double_strike ( fill_start )
  8401.                            := waiting_output_line.double_strike ( work_start ) ;
  8402.               filling_output_line.offset_strike ( fill_start )
  8403.                            := waiting_output_line.offset_strike ( work_start ) ;
  8404.               filling_output_line.underline     ( fill_start )
  8405.                            := waiting_output_line.underline     ( work_start ) ;
  8406.               filling_output_line.sub_or_supers ( fill_start )
  8407.                            := waiting_output_line.sub_or_supers ( work_start ) ;
  8408.             end if ;
  8409.             work_start := work_start + 1 ;
  8410.             fill_start := fill_start + 1 ;
  8411.           end loop ;
  8412.           -- now, set all other items
  8413.           -- filling_output_line.start_position is already set
  8414.           filling_output_line.stop_position := filling_output_line.stop_position
  8415.                                                      + ending_position_length ;
  8416.           if Current_Formatting_Parameters.Justification_On then
  8417.             filling_output_line.justify_to := rightmost_text_position ;
  8418.           else
  8419.             filling_output_line.justify_to := filling_output_line.stop_position;
  8420.           end if ;
  8421.           -- now, we must check for dots....
  8422.           -- note that we might do this a few times for a line, but it is to
  8423.           -- ensure that the other routines always get a clean copy of the
  8424.           -- text line
  8425.           filling_output_line.character_count := fill_start - 1 ;
  8426.           if filling_output_line.wordspace_count = 0 then
  8427.             -- adding to blank line
  8428.             filling_output_line.wordspace_count := number_of_words - 1 ;
  8429.           else
  8430.             -- adding to line with other text...
  8431.             filling_output_line.wordspace_count := 
  8432.                      filling_output_line.wordspace_count + number_of_words ;
  8433.           end if ;
  8434.           if Current_formatting_parameters.Delay_Justification_Till_After_Dots 
  8435.           and then filling_output_line.start_position 
  8436.                                   = leftmost_para_text_position then
  8437.             -- dots on and we are starting a paragraph...
  8438.             filling_output_line.first_justify := look_for_dots ;
  8439.           else
  8440.             filling_output_line.first_justify := 1 ;
  8441.           end if ;
  8442.           -- That is it!  Everything is set....
  8443.           text_waiting_inside_filled_paragraph := true ;
  8444.         end Move_Over_Current_Text ;
  8445.          
  8446.         procedure Output_Filling_Line is
  8447.         begin -- Output_Filling_Line 
  8448.           kind_of_move_after_line                      := move_forward_on_page ;
  8449.           amount_waiting_to_move_vertically_after_line := 
  8450.                                                  current_vertical_motion_index ;
  8451.           move_before_current_line ( false , first_line_of_filled_paragraph ) ;
  8452.           -- not last line of para, but first line of para (possibly) ...
  8453.           tidy_up_and_output_filled_line ;
  8454.           first_line_of_filled_paragraph := false ;
  8455.           -- now that we have output the first line of this paragraph, and
  8456.           -- we have overflowed, meaning that we have a paragraph of at least
  8457.           -- two lines, then we are no longer on the first line of the parag.
  8458.         end Output_Filling_Line ;
  8459.          
  8460.         procedure clear_up_filling_line is
  8461.           -- reset back to correct values for blank line
  8462.         begin -- clear_up_filling_line
  8463.           filling_output_line.start_position := leftmost_text_position ;
  8464.           filling_output_line.stop_position  := leftmost_text_position ;
  8465.           just_did_tab_command := false ;
  8466.           room_in_filling_line      := rightmost_text_position 
  8467.                                          - filling_output_line.stop_position ;
  8468.                                          -- that is how much room is available
  8469.                                          -- to add to the current line.
  8470.           waiting_width := 0 ;
  8471.         end clear_up_filling_line ;
  8472.          
  8473.         procedure move_over_a_word is
  8474.           -- a word has ended, move correct amount over....
  8475.         begin
  8476.           number_of_words := number_of_words + 1 ;
  8477.           last_char_breakable_space := false ;
  8478.           If work_without_space_length > room_in_filling_line 
  8479.           and then ( ( number_of_words > 1 )
  8480.                    or else ( filling_output_line.character_count > 0 ) ) then
  8481.             -- if we have a word which will overflow the output line
  8482.             -- and then we will move a single word over and not the others
  8483.             -- or else the line containing the text waiting for filling output
  8484.             -- is not blank, then output it.  If the new word is too long for
  8485.             -- the margins, but no words are on the current line, add it to
  8486.             -- the current line anyway.....because otherwise we will loop 
  8487.             -- forever.  Finally, if the word fits, just keep working and
  8488.             -- skip this area of code....
  8489.             if number_of_words > 1 then
  8490.               number_of_words := number_of_words - 1 ;
  8491.             end if ;
  8492.             move_over_current_text ; -- move current text to output area
  8493.             output_filling_line    ; -- and output that text.
  8494.             clear_up_filling_line  ; -- and set up for new line.
  8495.             -- note, if it is a single word, we let it fit anyway!
  8496.             -- move line_start_position .. work_without_space_position over
  8497.             -- starting at filling_output_line.character_count + 1
  8498.             number_of_words := 1 ; -- for current word
  8499.             line_start_position   := last_successfull_position + 1 ;
  8500.             work_position_length  := work_position_length 
  8501.                                               - last_successfull_length ;
  8502.               -- because even though we did not put spaces into the last
  8503.               -- line (at the end), they are thrown away...
  8504.             work_without_space_length  := work_without_space_length
  8505.                                               - last_successfull_length ;
  8506.           elsif waiting_width > 0 then
  8507.             prepare_for_adding_line ;
  8508.             waiting_width := 0 ;
  8509.           end if ;
  8510.           -- now, we can just prepare to move over...
  8511.           last_successfull_position       := work_position - 1              ;
  8512.           last_successfull_length         := work_position_length           ;
  8513.           Ending_position_so_far          := work_without_space_position    ;
  8514.           Ending_Position_Length          := work_without_space_length      ;
  8515.         end move_over_a_word ;
  8516.          
  8517.       begin -- add_this_line_to_paragraph
  8518.         if text_waiting_inside_filled_paragraph then
  8519.           waiting_width := filling_trailing_spaces *
  8520.                                 current_font.width ( extended_space ) ;
  8521.           if just_did_tab_command then
  8522.             -- must move to correct position 
  8523.             -- for now, we cannot get here because we always end a para.
  8524.             null ;
  8525.              
  8526.           end if ;
  8527.         else
  8528.           waiting_width := 0 ;
  8529.           -- we need to set the line boundries
  8530.           first_line_of_filled_paragraph := true ;
  8531.           if just_did_tab_command then
  8532.             -- must move to correct position 
  8533.             filling_output_line.start_position := tab_requested_to_position   ;
  8534.             filling_output_line.stop_position  := tab_requested_to_position   ;
  8535.           else
  8536.             filling_output_line.start_position := leftmost_para_text_position ;
  8537.             filling_output_line.stop_position  := leftmost_para_text_position ;
  8538.           end if ;
  8539.         end if ;
  8540.         just_did_tab_command := false ;
  8541.         room_in_filling_line      := rightmost_text_position 
  8542.                                         - filling_output_line.stop_position 
  8543.                                         - waiting_width ;
  8544.                                          -- that is how much room is available
  8545.                                          -- to add to the current line.
  8546.         -- first, eat leading spaces
  8547.         while ( line_start_position <= waiting_output_line.character_count )
  8548.         and then waiting_output_line.the_character ( line_start_position ) 
  8549.                                                = extended_space loop
  8550.           line_start_position := line_start_position + 1 ;
  8551.         end loop ;
  8552.         if line_start_position > waiting_output_line.character_count then
  8553.           -- no text on this line....Skip entire operation
  8554.           return ;
  8555.         end if ;
  8556.         -- line start position is where the next set of chararacters will start
  8557.         -- to come from to move over into output stream...
  8558.         last_successfull_position := line_start_position - 1 ;
  8559.                 -- last good output position is the line start position - 1 ;
  8560.         work_position             := line_start_position - 1 ;--last worked char
  8561.         loop
  8562.         exit when work_position >= waiting_output_line.character_count ;
  8563.           -- exit this loop when we have worked the last valid character
  8564.           -- we don't use a for loop because we want to know what work_position
  8565.           -- is after leaving the loop
  8566.           work_position := work_position + 1 ;
  8567.           c := waiting_output_line.the_character ( work_position ) ;
  8568.           w := waiting_output_line.the_width     ( work_position ) ;
  8569.           -- we get here knowing that the last char was or was not a possible
  8570.           -- break chararacter.  If it was, and the new chararacter is not a
  8571.           -- space, then process for end of a work... If not, just move on to
  8572.           -- the next character, adding to lengths...
  8573.           if last_char_breakable_space
  8574.           and then c /= extended_space then
  8575.             -- end of trailing spaces after word, work it...
  8576.             move_over_a_word ;
  8577.             -- rsc!!! waiting_width    := 0  ;
  8578.           elsif c = extended_space 
  8579.           and then not last_char_breakable_space 
  8580.           and then not waiting_output_invalid_breaks ( work_position ) then
  8581.             -- must set up as start of trailing space
  8582.             work_without_space_position  := work_position - 1    ;
  8583.             work_without_space_length    := work_position_length ;
  8584.             last_char_breakable_space    := true ;
  8585.           end if ;
  8586.           -- now, in any case, move over the current character....
  8587.           Work_Position_Length := Work_Position_Length + w ;
  8588.         end loop ;
  8589.         -- move over the remainder ..
  8590.         if not last_char_breakable_space then
  8591.           -- no trailing_spaces on this line...
  8592.           if waiting_output_line.the_character ( work_position )
  8593.                       = extended_character ( character'pos ( '-' ) ) then
  8594.             -- a hyphenated word ending at line end...
  8595.             temporary_waiting_filling_spaces := 0 ;
  8596.           else
  8597.             temporary_waiting_filling_spaces := 1 ;
  8598.           end if ;
  8599.           work_without_space_position  := work_position        ;
  8600.           work_without_space_length    := work_position_length ;
  8601.           work_position := work_position + 1 ; -- to pretend that a ' ' is there
  8602.         else
  8603.           temporary_waiting_filling_spaces := work_position 
  8604.                                       - work_without_space_position ;
  8605.         end if ;
  8606.         work_position := work_position + 1 ;
  8607.           -- to pretend that we have moved to the first char of a new word
  8608.         move_over_a_word ;  -- really forces out a line if the word before
  8609.                             -- this ends a line...
  8610.         if waiting_width > 0 then
  8611.           prepare_for_adding_line ;
  8612.           waiting_width := 0 ;
  8613.         end if ;
  8614.         last_successfull_position       := work_position - 1              ;
  8615.         last_successfull_length         := work_position_length           ;
  8616.         Ending_position_so_far          := work_without_space_position    ;
  8617.         Ending_Position_Length          := work_without_space_length      ;
  8618.         -- and now, do the current word...
  8619.         move_over_current_text ;
  8620.         -- Now, to remember for later....
  8621.         filling_trailing_spaces := temporary_waiting_filling_spaces ;
  8622.         filling_trailing_spaces_are_underlined
  8623.                     := current_formatting_parameters.current_character_changes 
  8624.                                   ( Underline_Continuous ) ;
  8625.       end add_this_line_to_paragraph ;
  8626.        
  8627.       Procedure compress_input_line ( only_right : in boolean ) is
  8628.         start_ind  : integer := 1 ;
  8629.         ending_ind : integer := input_line_length ;
  8630.       begin
  8631.         if not only_right then
  8632.           -- we are to compress both sides...
  8633.           While start_ind <= ending_ind
  8634.           and then Input_Line(start_ind) = extended_space loop
  8635.             start_ind := start_ind + 1 ;
  8636.           end loop ;
  8637.         end if ;
  8638.         while ending_ind >= start_ind 
  8639.         and then Input_Line(ending_ind) = extended_space loop
  8640.           ending_ind := ending_ind - 1 ;
  8641.         end loop ;
  8642.         if start_ind > ending_ind then
  8643.           Input_Line_Length := 0 ;
  8644.         else
  8645.           if start_ind > 1 then
  8646.             for posn in start_ind .. ending_ind loop
  8647.               Input_Line ( posn - start_ind + 1 ) := Input_Line ( posn ) ;
  8648.             end loop ;
  8649.           end if ;
  8650.           Input_Line_Length := ending_ind - start_ind + 1 ;
  8651.         end if ;
  8652.       end compress_input_line ;
  8653.  
  8654.       procedure finish_print_work_for_an_old_document is
  8655.       begin -- finish_print_work_for_an_old_document
  8656.         finish_printer_globals_for_an_old_document  ;
  8657.         finish_print_out_for_an_old_document        ;
  8658.         finish_printer_misc_for_an_old_document     ;
  8659.         finish_printer_commands_for_an_old_document ;
  8660.         if Index_File_Is_Open then
  8661.           text_io.close(index_output_file);
  8662.         end if ;
  8663.       end finish_print_work_for_an_old_document ;
  8664.      
  8665.     begin
  8666.       --
  8667.       -- Initialize
  8668.       --
  8669.       current_environment := initial_environment     ;
  8670.       alt_in_file_name    := no_file                 ;
  8671.       initialize_printer_globals_for_a_new_document  ;
  8672.       initialize_print_out_for_a_new_document        ;
  8673.       initialize_printer_misc_for_a_new_document     ;
  8674.       initialize_print_work_for_a_new_document       ;
  8675.       -- Note that the printer commands must be initialized after print_work
  8676.       initialize_printer_commands_for_a_new_document ;
  8677.       -- 
  8678.       -- now, ready to go to work on the document
  8679.       --
  8680.       loop
  8681.         get_line ; -- get the next line...
  8682.       exit when not input_line_contains_text ; -- must be done...
  8683.       exit when user_interrupt ; -- or is an exception raised ? 
  8684.         if Current_Formatting_Parameters.Filling_On then
  8685.           input_line_to_output_line ;
  8686.           add_this_line_to_paragraph ;
  8687.         else
  8688.           -- work the movement
  8689.           kind_of_move_after_line                      := move_forward_on_page ;
  8690.           amount_waiting_to_move_vertically_after_line := 
  8691.                                                  current_vertical_motion_index ;
  8692.           move_before_current_line ;
  8693.           -- now, we need to do a little compression work on the input line
  8694.           case current_formatting_parameters.line_modification is
  8695.             when nothing       => compress_input_line (  true ) ;
  8696.             when center_mod    => compress_input_line ( false ) ;
  8697.             when right_justify => compress_input_line ( false ) ;
  8698.             when to_left_margin=> null ; -- this is only for page numbers, etc.
  8699.           end case ;
  8700.           if input_line_length > 0 then
  8701.             -- we have to do something ...
  8702.             input_line_to_output_line ;
  8703.             -- now, need to reset the character changes back to what it was when
  8704.             -- this routine was called, because with filling off, temporary 
  8705.             -- changes are only kept for the current line....
  8706.             current_formatting_parameters.current_character_changes
  8707.                   := current_formatting_parameters.permanent_character_changes ;
  8708.             -- end of work with character changes...
  8709.             modify_a_line ( waiting_output_line ) ;
  8710.             send_input_text_to_output_device ;
  8711.           end if ;
  8712.         end if ;
  8713.       end loop ;
  8714.       --
  8715.       -- and finish any loose ends
  8716.       --
  8717.       finish_print_work_for_an_old_document       ;
  8718.       --
  8719.       -- done with a document
  8720.       --
  8721.     exception
  8722.       --
  8723.       when users_requested_abort        =>
  8724.                               if not Need_To_Start_Page then
  8725.                                 end_a_page ;
  8726.                               end if ;
  8727.                               execute_printer_command(end_last_page)        ;
  8728.                               finish_print_work_for_an_old_document         ;
  8729.                               raise users_requested_abort                   ;
  8730.       --
  8731.       when last_selected_page_printed   =>
  8732.                               execute_printer_command(end_last_page)        ;
  8733.                               finish_print_work_for_an_old_document         ;
  8734.                               -- and we end normally, because we might want
  8735.                               -- several copies of a selected range of pages
  8736.       --
  8737.       when fatal_output_error           =>
  8738.                               finish_print_work_for_an_old_document         ;
  8739.                               raise fatal_output_error                      ;
  8740.       --
  8741.     end print_a_single_document ;
  8742.       
  8743.     procedure end_output ( printout_aborted_by_user_intervention : boolean ) is
  8744.       c : character ;
  8745.       ok : boolean  ;
  8746.     begin -- end_output
  8747.       -- first step in ending - tell them we're done
  8748.       if not printout_aborted_by_user_intervention 
  8749.       and then Initial_Environment.Show_Output_Status then
  8750.         clear_end_of_screen ( master_window , 22 , 1 ) ;
  8751.         otsxy(20,22,"Complete....Hit space to continue!");
  8752.         bell ;
  8753.       end if ;
  8754.       -- next, if not going to screen, we might have to do some work
  8755.       if Initial_Environment.Where_To /= to_screen then
  8756.         -- we have a file or printer out there
  8757.         -- stall, to preceed printer reset
  8758.         Execute_Printer_Command(printer_reset) ;
  8759.         if Initial_Environment.Where_To = to_file then
  8760.           -- we must close the file we were going to
  8761.           close_output_file ( ok ) ;
  8762.         elsif Initial_Environment.Where_To = to_printer then
  8763.           null ; -- release_printer ;
  8764.         end if ;
  8765.       end if ;
  8766.       if not printout_aborted_by_user_intervention 
  8767.       and then Initial_Environment.Show_Output_Status then
  8768.         wait_for_character(' ');
  8769.       end if ;
  8770.       -- if variable, then delete that command from command table...
  8771.     end end_output ;
  8772.      
  8773.     procedure end_an_entire_document is
  8774.     begin -- end_an_entire_document 
  8775.       if Initial_Environment.Inp_Source = fm_database then
  8776.         -- we must take that variable command name out of the tree....
  8777.         DELETE_NAME ( "variable_data_insertion" ,
  8778.                       command_tree      ) ;
  8779.       end if ;
  8780.     end end_an_entire_document ;
  8781.      
  8782.     procedure close_print_work is
  8783.     begin -- close_print_work 
  8784.       close_printer_globals  ;
  8785.       close_print_out        ;
  8786.       close_printer_misc     ;
  8787.       close_printer_commands ;
  8788.     end close_print_work ;
  8789.      
  8790.   begin -- print_work 
  8791.     global_initialize_print_work ;
  8792.   end print_work ;
  8793.     
  8794.   --$$$- PRNTWORK
  8795.  
  8796. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8797. --prntmain
  8798. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8799.  
  8800.   --$$$+ PRNTMAIN
  8801.  
  8802.   --
  8803.   -- File 0xx
  8804.   --
  8805.   -- Formatter Written By Robert S. Cymbalski
  8806.   --                      Science Applications International Corporation
  8807.   --                      Energy Systems Group
  8808.   --                      Ada Software Development Project Team
  8809.   --                      2280 U.S. Highway 19 North, Suite 120
  8810.   --                      Clearwater, Florida  33575
  8811.   --
  8812.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  8813.   --
  8814.   -- This is the master Print Routine...
  8815.    
  8816.   with text_io         ;
  8817.    
  8818.   with direct_IO   ;
  8819.    
  8820.   with string_library  ;
  8821.   use  string_library  ;
  8822.    
  8823.   with basic_io_system ;
  8824.    
  8825.   with crt_customization ;
  8826.   use  crt_customization ;
  8827.    
  8828.   with crt_windows     ;
  8829.   use  crt_windows     ;
  8830.    
  8831.   with Wordp_Globals   ;
  8832.   use  Wordp_Globals   ;
  8833.  
  8834.   with printer_globals ;
  8835.   use  printer_globals ;
  8836.     
  8837.   with print_in_to_out ;
  8838.    
  8839.   with print_out       ;
  8840.    
  8841.   with print_work      ;
  8842.   use  print_work      ;
  8843.    
  8844.   Package PRINT_MAIN is
  8845.   
  8846.     procedure TEXT_FORMATTER(SOURCE_FILE : in ASCII_TEXT_FILE_NAME 
  8847.                                                    ; -- := wp_globals.no_file ;
  8848.                              DESTINATION_FILE : in ASCII_TEXT_FILE_NAME 
  8849.                                                    ; -- := wp_globals.no_file ;
  8850.                              STARTING_ENVIRONMENT : in FORMATTER_ENVIRONMENT
  8851.                                                 ) ; --  := default_environment);
  8852.     -- This tool formats the SOURCE_FILE according to the default format
  8853.     -- and imbedded formatting commands.  The output is sent to the destination
  8854.     -- device or file.  
  8855.    
  8856.   end ;
  8857.    
  8858.   Package body PRINT_MAIN is
  8859.   
  8860.     type printer_save_block is
  8861.            record 
  8862.              printer : printer_type ;
  8863.              accessy : printer_accessories_type ;
  8864.            end record ;
  8865.      
  8866.     package save_block_io is new direct_IO(printer_save_block);
  8867.      
  8868.     procedure TEXT_FORMATTER(SOURCE_FILE : in ASCII_TEXT_FILE_NAME 
  8869.                                                   ; -- := wp_globals.no_file ;
  8870.                              DESTINATION_FILE : in ASCII_TEXT_FILE_NAME 
  8871.                                                    ; -- := wp_globals.no_file ;
  8872.                              STARTING_ENVIRONMENT : in FORMATTER_ENVIRONMENT
  8873.                                              ) is -- := default_environment) is
  8874.     -- This tool formats the SOURCE_FILE according to the default format
  8875.     -- and imbedded formatting commands.  The output is sent to the destination
  8876.     -- device or file.  
  8877.    
  8878.       Save_Block_File_name : constant ascii_text_file_name 
  8879.                                 := "PRINTDEF.ENV        " ;
  8880.                                  
  8881.       Ot_Option : character ; -- what is the current selected output option?
  8882.       Was_Successfull ,
  8883.       Please_Quit : boolean ;
  8884.        
  8885.       procedure restore_printer_settings is
  8886.         file_handle : save_block_io.file_type ;
  8887.         final_name  : ascii_text_file_name    ;
  8888.         p_save_block: printer_save_block      ;
  8889.         it_exists   : boolean                 ;
  8890.       begin -- restore_printer_settings
  8891.         -- sok_to_read(save_block_file_name, final_name , it_exists ) ;
  8892.         -- we want to use local file...
  8893.         -- if it_exists then
  8894.           -- save_block_io.open(file_handle,save_block_io.in_file,
  8895.                              -- no_blanks(final_name));
  8896.           -- save_block_io.read(file_handle,p_save_block);
  8897.           -- permanent_printer   := p_save_block.printer ;
  8898.           -- printer_accessories := p_save_block.accessy ;
  8899.         -- else
  8900.           -- must do defaults
  8901.           -- permanent_printer   := z_xerox ;
  8902.           -- printer_accessories := none    ;
  8903.         -- end if ;
  8904.         save_block_io.open(file_handle,save_block_io.in_file,
  8905.                            no_blanks( save_block_file_name ) ) ;
  8906.         save_block_io.read(file_handle,p_save_block);
  8907.         permanent_printer   := p_save_block.printer ;
  8908.         printer_accessories := p_save_block.accessy ;
  8909.       exception
  8910.         -- here only if the file exists but we were unable to read it
  8911.         when others => permanent_printer   := z_qume  ;
  8912.                        printer_accessories := none    ;
  8913.       end restore_printer_settings ;
  8914.        
  8915.       procedure save_printer_settings is
  8916.         file_handle : save_block_io.file_type ;
  8917.         final_name  : ascii_text_file_name    ;
  8918.         p_save_block: printer_save_block      ;
  8919.         it_exists   : boolean                 ;
  8920.       begin -- save_printer_settings
  8921.         p_save_block.printer := permanent_printer   ;
  8922.         p_save_block.accessy := printer_accessories ;
  8923.         sok_to_read(save_block_file_name, final_name , it_exists ) ;
  8924.         -- ok, here we can let it mess with us....
  8925.         if it_exists then
  8926.           save_block_io.open(file_handle,save_block_io.out_file,
  8927.                              no_blanks(final_name));
  8928.         else
  8929.           save_block_io.create(file_handle,save_block_io.out_file,
  8930.                                no_blanks(save_block_file_name));
  8931.         end if ;
  8932.         save_block_io.write(file_handle,p_save_block);
  8933.         save_block_io.close(file_handle);
  8934.       exception
  8935.         -- here only if the file exists but we were unable to read it
  8936.         when others => error( " Unable to correctly save printer settings " ,
  8937.                                not_fatal_error , operator_wait , short_beep ) ;
  8938.       end save_printer_settings ;
  8939.      
  8940.       procedure print_package_initialize is
  8941.         -- initialize by reading a file somewhere that keeps us
  8942.         -- posted to the current printer...
  8943.       begin -- print_package_initialize
  8944.         Initial_Environment := starting_environment ;
  8945.         if Initial_Environment.printer_brand = z_unknown then
  8946.           -- we need to find out about the printer defaults
  8947.           restore_printer_settings ;
  8948.           Initial_Environment.printer_brand       := permanent_printer   ;
  8949.           Initial_Environment.printer_accessories := printer_accessories ;
  8950.         else
  8951.           permanent_printer   := Initial_Environment.printer_brand ;
  8952.           printer_accessories := Initial_Environment.printer_accessories ;
  8953.         end if ;
  8954.         change_printer( Initial_Environment.Printer_Brand ) ;
  8955.       end print_package_initialize ;
  8956.      
  8957.       procedure get_options ( please_quit : out boolean ) is
  8958.         -- ask the user all of the appropriate questions , and then
  8959.         -- return please_quit as the signal to quit if they requested it
  8960.         -- this sets the current requested input and output files and
  8961.         -- the starting environment
  8962.         done_with_get_ready , 
  8963.         ready_for_printing  : boolean ;
  8964.      
  8965.         procedure set_printer is
  8966.          
  8967.           --###--RSC02 start
  8968.           tot_ps : constant integer :=  8 ; -- total printers
  8969.           half_ps : constant integer := 8 ; -- max in first column
  8970.           line_ps : constant integer := 7 ; -- first line for printers
  8971.           tot_as  : constant integer := 4 ; -- total accessories
  8972.           half_as : constant integer := 4 ; -- max in first column
  8973.           line_as : constant integer := 19 ; -- first line for accessories
  8974.           --###--RSC02 stop
  8975.             
  8976.           ch : character ;
  8977.           i  : integer ;
  8978.           temp : boolean ;
  8979.           good_options : character_set ;
  8980.           
  8981.           Procedure get_xy ( current_entry : in integer ; x,y : out integer ) is
  8982.           temp_entry : integer ;
  8983.           begin
  8984.             -- 1..29 are printers
  8985.             -- 30..40 are options
  8986.             if current_entry < 30 then
  8987.               -- is a printer
  8988.               if current_entry <= half_ps then
  8989.                 x := 2;
  8990.               else
  8991.                 x := 44 ;
  8992.               end if ;
  8993.               y := ( (current_entry - 1) mod half_ps ) + line_ps ;
  8994.               -- this does lines 7..15 for half_ps=8 and line_ps=7
  8995.             else
  8996.               -- this is an accessory
  8997.               temp_entry := current_entry - 30 ;
  8998.               if temp_entry <= half_as then
  8999.                 x := 2 ;
  9000.               else 
  9001.                 x := 44 ;
  9002.               end if ;
  9003.               y := ( (temp_entry - 1) mod half_as ) + line_as ;
  9004.             end if ;
  9005.           end get_xy ;
  9006.           
  9007.           Procedure pname(current_entry : in integer ; name : in string ;
  9008.                           value : in boolean ) is
  9009.             x , y : integer ;
  9010.           begin -- pname
  9011.             get_xy(current_entry,x,y) ; -- convert to x,y coordinates
  9012.             otsxy(x,y,name) ;
  9013.             if value then
  9014.               otsxy( x+31,y,"True") ;
  9015.             end if ;
  9016.           end pname ;
  9017.           
  9018.           Procedure Long is
  9019.           begin
  9020.             clear_window( master_window ) ;
  9021.             clear_prompt( master_window ) ;
  9022.             goto_prompt_line_column ( master_window , 1 , 2 ) ;
  9023.             put("Enter option to select or change (<space> to quit) ? ");
  9024. --###--RSC02 start
  9025. otsxy(3,2,"This is the routine to set up the computer for different types of");
  9026. otsxy(3,3,"printers and accessories.  Possible choices are grouped together.");
  9027. otsxy(3,4,"Only one option of a group may be selected at one time.");
  9028. pname( 1,"A : Draft Copy Printer"       , permanent_printer = z_pdumb       ) ;
  9029. pname( 2,"B : Qume Printer"             , permanent_printer = z_qume        ) ;
  9030. pname( 3,"C : Xerox 630 / Diablo 630"   , permanent_printer = z_xerox       ) ;
  9031. pname( 4,"D : Centronics 737 Printer"   , permanent_printer = z_cent737     ) ;
  9032. pname( 5,"E : Dataproducts"             , permanent_printer = z_dataproducts) ;
  9033. pname(31,"1 : No Accessories"           , printer_accessories = none        ) ;
  9034. pname(32,"2 : Tray Loader"              , printer_accessories = trayloader  ) ;
  9035. pname(33,"3 : Dual Tray Loader "        , printer_accessories = dual_tray   ) ;
  9036. pname(34,"4 : Mechanical Tray Loader"   , printer_accessories = mech_tray   ) ;
  9037. --###--RSC02 stop
  9038.           end long ;
  9039.           
  9040.           Procedure do_this ( current_entry , estart , enum : in integer ) is
  9041.             ii : integer ;
  9042.             x , y : integer ;
  9043.           begin -- do_this
  9044.             for ii in estart .. estart-1+enum loop
  9045.               get_xy(ii,x,y) ;
  9046.               x := x + 31 ; -- to offset past line of prompt
  9047.               if ii = current_entry then
  9048.                 otsxy(x,y,"True ") ;
  9049.               else
  9050.                 otsxy(x,y,"     ") ;
  9051.               end if ;
  9052.             end loop ;
  9053.           end do_this ;
  9054.           
  9055.         begin -- set_printer 
  9056.           long ;
  9057.           clear_set(good_options) ;
  9058.           good_options('0') := true ;
  9059.           good_options(' ') := true ;
  9060.           for cc in 'A' .. 'P' loop
  9061.             good_options(cc) := true ;
  9062.           end loop ;
  9063.           for cc in '1' .. '4' loop
  9064.             good_options(cc) := true ;
  9065.           end loop ;
  9066.           loop
  9067.             goto_prompt_line_column( master_window , 1 , 59 ) ;
  9068.             crt_windows.put(' ') ;
  9069.             goto_prompt_line_column( master_window , 1 , 59 ) ;
  9070.             ch := goodchar(good_options , ' ') ;
  9071.             case ch is
  9072.               --###--RSC02 starts
  9073.               when 'A' => do_this(1,1,tot_ps) ;
  9074.                           permanent_printer := z_pdumb           ;
  9075.               when 'B' => do_this(2,1,tot_ps) ;
  9076.                           permanent_printer := z_qume            ;
  9077.               when 'C' => do_this(3,1,tot_ps) ;
  9078.                           permanent_printer := z_xerox           ;
  9079.               when 'D' => do_this(4,1,tot_ps) ;
  9080.                           permanent_printer := z_cent737         ;
  9081.               when 'E' => do_this(5,1,tot_ps) ;
  9082.                           permanent_printer := z_dataproducts    ;
  9083.               --###--RSC02 stops
  9084.               when '1' => do_this(31,31,tot_as) ;
  9085.                           printer_accessories := none            ;
  9086.               when '2' => do_this(32,31,tot_as) ;
  9087.                           printer_accessories := trayloader      ;
  9088.               when '3' => do_this(33,31,tot_as) ;
  9089.                           printer_accessories := dual_tray       ;
  9090.               when '4' => do_this(34,31,tot_as) ;
  9091.                           printer_accessories := mech_tray       ;
  9092.               when others => null ;
  9093.             end case ;
  9094.             exit when ch = ' ' ;
  9095.           end loop ;
  9096.           Initial_Environment.printer_brand       := permanent_printer   ;
  9097.           Initial_Environment.printer_accessories := printer_accessories ;
  9098.           change_printer ( permanent_printer ) ;
  9099.           save_printer_settings ;
  9100.         end set_printer ;
  9101.  
  9102.         Procedure Show_options is
  9103.           made_changes : boolean ;
  9104.           s : string(1 .. 8) ;
  9105.               
  9106.           procedure put ( d : basic_io_system.timer ) is
  9107.           begin -- put 
  9108.             case d.day_of_week is
  9109.               when basic_io_system.sunday     => put( "Sun" ) ;
  9110.               when basic_io_system.monday     => put( "Mon" ) ;
  9111.               when basic_io_system.tuesday    => put( "Tue" ) ;
  9112.               when basic_io_system.wednesday  => put( "Wed" ) ;
  9113.               when basic_io_system.thursday   => put( "Thu" ) ;
  9114.               when basic_io_system.friday     => put( "Fri" ) ;
  9115.               when basic_io_system.saturday   => put( "Sat" ) ;
  9116.             end case ;
  9117.             put(" ");
  9118.             case d.month is
  9119.               when  1 => put( "Jan" ) ;
  9120.               when  2 => put( "Feb" ) ;
  9121.               when  3 => put( "Mar" ) ;
  9122.               when  4 => put( "Apr" ) ;
  9123.               when  5 => put( "May" ) ;
  9124.               when  6 => put( "Jun" ) ;
  9125.               when  7 => put( "Jul" ) ;
  9126.               when  8 => put( "Aug" ) ;
  9127.               when  9 => put( "Sep" ) ;
  9128.               when 10 => put( "Oct" ) ;
  9129.               when 11 => put( "Nov" ) ;
  9130.               when 12 => put( "Dec" ) ;
  9131.             end case ;
  9132.             put(" ");
  9133.             put( d.day , 2 ) ;
  9134.             put(" ");
  9135.             put( d.year , 4 ) ;
  9136.             put(" ");
  9137.             put( d.hour , 2 ) ;
  9138.             put(":");
  9139.             if d.minute < 10 then
  9140.               put("0");
  9141.               put( d.minute , 1 ) ;
  9142.             else
  9143.               put( d.minute , 2 ) ;
  9144.             end if ;
  9145.           end put ;
  9146.      
  9147.           Procedure dateout is
  9148.           begin -- dateout
  9149.             put("[");
  9150.             put(basic_io_system.clock);
  9151.             put("]");
  9152.           end ;
  9153.         
  9154.           Procedure printout is
  9155.           begin
  9156.             crt_windows.put("[Current Printer is ");
  9157.             case z_printer is
  9158.               --###--RSC02 starts
  9159.               when z_pdumb        => crt_windows.put("Draft Copy Printer");
  9160.               when z_qume         => crt_windows.put("Qume");
  9161.               when z_xerox        => crt_windows.put("Xerox/Diablo 630");
  9162.               when z_cent737      => crt_windows.put("Centronics 737");
  9163.               when z_dataproducts => crt_windows.put("Dataproducts");
  9164.               when others         => crt_windows.put("HELP! Printer Unknown");
  9165.               --###--RSC02 stops
  9166.             end case ;
  9167.             crt_windows.put(']');
  9168.           end printout ;
  9169.               
  9170.           Procedure show_status ( s : string ) is
  9171.           begin
  9172.             clear_window ( master_window ) ;
  9173.             clear_prompt ( master_window ) ;
  9174.             otsxy(20,11,"Please Wait - ");
  9175.             crt_windows.put(s) ;
  9176.           end show_status ;
  9177.             
  9178.         begin -- show_options
  9179.           change_printer( permanent_printer ) ;
  9180.           clear_prompt( master_window ) ;
  9181.           clear_window( master_window ) ;
  9182.           goto_line_column( master_window , 23 , 1 ) ;
  9183.           -- put(
  9184.           -- "SAIC Text Formatter modified from Program " &
  9185.           -- "Copyright (c) 1984, R. S. Cymbalski"
  9186.           -- );
  9187.           goto_line_column( master_window , 23 , 1 ) ;
  9188.           printout;
  9189.           goto_line_column( master_window , 23 , 54 ) ;
  9190.           dateout;
  9191.           otsxy(26,3,"SAIC Text Formatter Print Menu");
  9192.           otsxy(20,8,"Options:");
  9193.           otsxy(22,10,"P : Print Documents or Form Letters");
  9194.           otsxy(22,11,"V : Variable Data List Merge");
  9195.           otsxy(22,12,"S : Set Printer Type ");
  9196.           otsxy(22,14,"Q : Quit") ;
  9197.           otsxy(20,16,"Enter Option: ");
  9198.           Ot_Option := char_or_abort( 'Q' , 'P' , 'V' , 'S' , 'Q' ) ;
  9199.           clear_window( master_window ) ;
  9200.           clear_prompt( master_window ) ;
  9201.           if Ot_Option = 'S' then
  9202.             set_printer ;
  9203.           elsif Ot_Option = 'Q' then
  9204.             null ;
  9205.           elsif Ot_Option = 'P' then
  9206.             Initial_Environment.Inp_Source := fm_text ;
  9207.           else
  9208.             Initial_Environment.Inp_Source := fm_database ;
  9209.           end if ;
  9210.         end show_options ;
  9211.          
  9212.         Procedure goodname(the_file_to_check : input_file_type          ;
  9213.                            line_number_to_use: window_line_number       ;
  9214.                            prompt_to_use     : string                   ;
  9215.                            the_file_name     : out ascii_text_file_name ;
  9216.                            file_is_ok_to_read: out boolean              ) is
  9217.           form , default : ascii_text_file_name := no_file ;
  9218.           fname : ascii_text_file_name ;
  9219.           ok_to_read : boolean ;
  9220.         begin -- goodname 
  9221.           ok_to_read := false ;
  9222.           loop 
  9223.             clear_end_of_screen( master_window , line_number_to_use , 1 ) ;
  9224.             goto_line_column( master_window , line_number_to_use , 2 ) ;
  9225.             put("Enter ");
  9226.             put(compress(prompt_to_use));
  9227.             put(" File Name ( or <return> to abort ) ");
  9228.             -- bell ;
  9229.             fname := get_input_filename_or_return ;
  9230.           exit when fname = no_file ;
  9231.             open_for_read( the_file_to_check , fname , ok_to_read ) ;
  9232.           exit when file_is_ok_to_read ;
  9233.             error( " Invalid File Name, Try Again.  " ,
  9234.                    not_fatal_error , operator_wait , short_beep ) ;
  9235.           end loop ;
  9236.           the_file_name := fname ;
  9237.           file_is_ok_to_read := ok_to_read ;
  9238.         end goodname ;
  9239.         
  9240.         Procedure Get_Ready_For_Printing ( done_with_get_ready : out boolean ;
  9241.                                            ready_for_printing  : out boolean) is
  9242.           new_file_name    : ascii_text_file_name ;
  9243.           re_try_get_ready : exception ;
  9244.           howout           : character ;
  9245.           ok               : boolean   ;
  9246.           
  9247.           procedure get_output_file_name is 
  9248.             done : boolean ;
  9249.           begin -- get_output_file_name
  9250.             done := false ;
  9251.             loop
  9252.               clear_end_of_screen( master_window , 21 ,  2 ) ;
  9253.               goto_line_column   ( master_window , 21 ,  2 ) ;
  9254.               put("  Enter Output File Name ( or <return> to abort ) => ") ;
  9255.               new_file_name := get_output_filename_or_return ;
  9256.               if new_file_name = no_file then
  9257.                 done := true ; -- fall through
  9258.               elsif new_file_name( 1 ) = ascii.esc then
  9259.                 -- an error, the file name did not exist
  9260.                 error(" File """ 
  9261.                                     & compress(new_file_name
  9262.                          ( 2 .. new_file_name'length ) )
  9263.                                     & """ is an invalid name." ,
  9264.                        not_fatal_error , operator_wait , short_beep ) ;
  9265.               elsif file_exists ( new_file_name ) then
  9266.                 -- we must confirm that they want to save it
  9267.                 clear_end_of_screen( master_window , 23 ,  2 ) ;
  9268.                 goto_line_column( master_window , 23 , 2 ) ;
  9269.                 put("  File """ & compress(new_file_name) 
  9270.                                 & """ already exists.  ");
  9271.                 put("  Delete and continue (Y/N) ? ");
  9272.                 done := char_or_abort( 'N' , 'Y' , 'N' ) = 'Y' ;
  9273.               else
  9274.                 done := true ; -- because it does not exist...
  9275.               end if ;
  9276.             -- need to set the default environment
  9277.             exit when done ;
  9278.             end loop ;
  9279.           end get_output_file_name ;
  9280.            
  9281.           Procedure set_up_for_the_output is
  9282.           begin
  9283.             -- first, do we output fancy or plain?
  9284.             if (howout = 'A') or (howout = 'B') or ( howout = 'E' ) then
  9285.               -- E is test option...
  9286.               Initial_Environment.Ot_Format := ot_fancy ;
  9287.             else 
  9288.               Initial_Environment.Ot_Format := ot_plain ;
  9289.               change_printer(z_pdumb) ; 
  9290.             end if ;
  9291.             -- then where does the output go ?
  9292.             if ( howout = 'A' ) or ( howout = 'E' ) then
  9293.               Initial_Environment.Where_To := to_printer ;
  9294.               if howout = 'A' then
  9295.                 new_file_name := default_printer ;
  9296.               else
  9297.                 new_file_name := "CON2:               " ;
  9298.               end if ;
  9299.             elsif howout = 'C' then
  9300.               Initial_Environment.Where_To := to_screen ;
  9301.               new_file_name := default_console ;
  9302.             else
  9303.               Initial_Environment.Where_To := to_file ;
  9304.             end if ;
  9305.             -- finally are we doing a natural spool ?
  9306.             if Initial_Environment.Where_To = to_printer 
  9307.             and then howout /= 'E' then -- not testing...
  9308.               -- do we have continuous forms ?
  9309.               goto_line_column ( master_window , 21 , 2 ) ;
  9310.               put("Print on Continuous Forms ( Y or N ) ? ");
  9311.               Initial_Environment.continuous_forms 
  9312.                           := char_or_abort( 'Y' , 'N' , 'Y' ) = 'Y' ;
  9313.             else
  9314.               Initial_Environment.continuous_forms := true ;
  9315.             end if ;
  9316.             if (howout = 'B') or (howout = 'D') then
  9317.               -- find a file name
  9318.               get_output_file_name ;
  9319.               if new_file_name = no_file then
  9320.                 raise re_try_get_ready ;
  9321.               end if ;
  9322.             end if ;
  9323.             formatter_requested_output_file_name := new_file_name ;
  9324.           end set_up_for_the_output ;
  9325.             
  9326.         begin -- get_ready_for_printing
  9327.           loop
  9328.             show_options ; -- show the options and get a response
  9329.             exit when ( Ot_Option = 'V' ) or ( Ot_Option = 'P' )
  9330.                    or ( Ot_Option = 'Q' ) ;
  9331.           end loop ;
  9332.           If Ot_Option = 'Q' then
  9333.             done_with_get_ready := true ;
  9334.             ready_for_printing  := false ;
  9335.           else
  9336.             -- (Ot_Option = 'P') or (Ot_Option = 'V')  
  9337.             --get a file name for working into output
  9338.             clear_window( master_window ) ;
  9339.             clear_prompt( master_window ) ;
  9340.             goodname(main_input_file , 2 , "Text Input" , new_file_name , ok ) ;
  9341.             if not ok then
  9342.               raise re_try_get_ready ;
  9343.             end if ;
  9344.             formatter_requested_input_file_name := new_file_name ;
  9345.             -- we might later take any leading disk name and save it so that
  9346.             -- inserted files can check the same disk
  9347.             if Ot_Option = 'V' then
  9348.               -- variable data list insertion
  9349.               goodname( variable_input_file , 4 , "Variable Data" ,
  9350.                         new_file_name , ok ) ;
  9351.               if not ok then
  9352.                 raise re_try_get_ready ;
  9353.               end if ;
  9354.               Initial_Environment.Database_File_Name := New_File_Name ;
  9355.               Initial_Environment.Number_Of_Copies_to_print := 1 ; 
  9356.             elsif Ot_Option = 'P' then
  9357.               -- how many copies ?
  9358.               goto_line_column ( master_window , 4 , 2 ) ;
  9359.               put("Enter total number of copies desired => ");
  9360.               Initial_Environment.Number_Of_Copies_to_print 
  9361.                                           := get_number( 4, 50, 0, 999, 3, 1 ) ;
  9362.               if Initial_Environment.Number_Of_Copies_to_print = 0 then
  9363.                 Initial_Environment.Number_Of_Copies_to_print := 1 ;
  9364.               end if ;
  9365.             -- else condition can never be met
  9366.             end if ;
  9367.             -- next, find the first and last pages to print
  9368.             goto_line_column( master_window , 6 , 2 ) ;
  9369.             put("Enter First Page To Print (<return> for all pages) ?");
  9370.             Initial_Environment.First_Page_To_Print 
  9371.                            := get_number(  6 , 65 , 0 , 999 , 3 , 0 ) ;
  9372.             if Initial_Environment.First_Page_To_Print = 0 then
  9373.               Initial_Environment.First_Page_To_Print :=    1 ;
  9374.               Initial_Environment.Last_Page_To_Print  := 9999 ;
  9375.               goto_line_column ( master_window , 6 , 65 ) ;
  9376.               put( 1 , 3 ) ; -- put a 1 in position using 3 columns
  9377.             else
  9378.               goto_line_column( master_window , 8 , 2 ) ;
  9379.               put(
  9380.               "Enter Last Page To Print (<return> for all remaining pages) ?");
  9381.               Initial_Environment.Last_Page_To_Print 
  9382.                            := get_number( 8 , 65 , 0 , 999 , 3 , 0 ) ;
  9383.               if Initial_Environment.Last_Page_To_Print = 0 then
  9384.                 Initial_Environment.Last_Page_To_Print := integer'last ;
  9385.               end if ;
  9386.             end if ;
  9387.             otsxy(5,10,"Output Options:");
  9388.             otsxy(7,12,"A : Print Output on Printer Immediately");
  9389.             otsxy(7,13,"B : Save Output into a File for Printing Later");
  9390.             otsxy(7,14,"C : Display Output on Screen");
  9391.             otsxy(7,15,"D : Put Output into a File for later editing");
  9392.             otsxy(7,17,"Q : Quit Printout and Return to Print Menu");
  9393.             otsxy(5,19,"Option ? ");
  9394.             howout := char_or_abort( 'E' , 'A' , 'B' , 'C' , 'D' , 'E', 'Q' ) ;
  9395.             --
  9396.             -- E added for CON2: output TEST -- RSC -- RSC
  9397.             -- Default should be changed back to 'A' after testing...
  9398.             --
  9399.             if howout = 'Q' then
  9400.               done_with_get_ready := false ;
  9401.               ready_for_printing  := false ;
  9402.             else
  9403.               set_up_for_the_output ;
  9404.               done_with_get_ready := true ;
  9405.               ready_for_printing  := true ;
  9406.             end if ;
  9407.           end if ;
  9408.         exception
  9409.           when re_try_get_ready => done_with_get_ready := false ;
  9410.                                    ready_for_printing  := false ;
  9411.         end get_ready_for_printing ;
  9412.  
  9413.       begin -- get_options
  9414.         loop
  9415.           get_ready_for_printing ( done_with_get_ready , ready_for_printing ) ;
  9416.         exit when done_with_get_ready ;
  9417.         end loop ;
  9418.         please_quit := not ready_for_printing ;
  9419.       end get_options ;
  9420.        
  9421.       procedure try_printing ( was_successfull : out boolean ) is
  9422.         -- try printing using the starting environment and
  9423.         -- requested input and output files
  9424.         -- return was_successfull as false if we can't operate with
  9425.         -- the selected options/files/devices
  9426.          
  9427.         final_name : ascii_text_file_name ;
  9428.         successfull : boolean ;
  9429.         unsuccessfull : exception ;
  9430.         printout_aborted_by_user_intervention : boolean := false ;
  9431.         ok              : boolean ;
  9432.         printout_completed : boolean := false ;
  9433.          
  9434.       begin -- try_printing
  9435.         copies_printed_so_far := 0 ;
  9436.         ot_file_name := formatter_requested_output_file_name ;
  9437.         if Initial_Environment.Inp_Source = fm_database then  
  9438.           -- we have a database reference
  9439.           initialize_variable_data_file ;
  9440.         end if ;
  9441.         do_purge(formatter_requested_output_file_name) ;
  9442.         create_output_file   ( formatter_requested_output_file_name ,
  9443.                                successfull ) ; 
  9444.         if not successfull then
  9445.           -- error because unable to open the output file....
  9446.           error( " File """ 
  9447.                  & string_library.compress
  9448.                                          (formatter_requested_output_file_name)
  9449.                  & """ cannot be opened." , not_fatal_error ,
  9450.                  operator_wait , short_beep ) ;
  9451.           raise unsuccessfull ;
  9452.         end if ;
  9453.         loop
  9454.           open_for_read(main_input_file,formatter_requested_input_file_name,ok);
  9455.           if not ok then
  9456.             error( " File """ 
  9457.                    & string_library.compress
  9458.                                            (formatter_requested_input_file_name)
  9459.                    & """ does not exist." , not_fatal_error ,
  9460.                    operator_wait , short_beep ) ;
  9461.             raise unsuccessfull ;
  9462.           end if ;
  9463.           if Initial_Environment.Inp_Source = fm_database then
  9464.             Initialize_For_New_Data ( ok ) ;
  9465.           else
  9466.             ok := true ;
  9467.           end if ;
  9468.           if ok then
  9469.             print_a_single_document ;
  9470.             -- now, we have one of two situations :
  9471.             -- 1) We are coming from a database (and need a new record)
  9472.             -- 2) We are just doing a regular file
  9473.             if (Initial_Environment.Inp_Source /= fm_database) then
  9474.               -- if this is not a database access, of if Test, then test for end
  9475.               copies_printed_so_far := copies_printed_so_far + 1 ; 
  9476.               -- increment the copy counter
  9477.               if (copies_printed_so_far 
  9478.                          >= Initial_Environment.Number_Of_Copies_to_print ) then
  9479.               -- we have completed each asked for copy
  9480.                 end_output ( false ) ;
  9481.                 printout_completed := true ;
  9482.               end if ;
  9483.               -- otherwise, we want to end at the next part
  9484.             end if ;
  9485.           else
  9486.             end_output ( false ) ;
  9487.             printout_completed := true ;
  9488.           end if ;
  9489.           was_successfull := true ;
  9490.         exit when printout_completed ;
  9491.         end loop ;
  9492.         end_an_entire_document ;
  9493.       exception
  9494.         when work_fatal_error_abort       => -- we get here because we cannot 
  9495.                                              -- print a document ... it is only
  9496.                                              -- raised by print_work.  In fact,
  9497.                                              -- we cannot even get started
  9498.                                              -- trying to print the document...
  9499.                                              was_successfull := false ;
  9500.                                              end_an_entire_document ;
  9501.         when unsuccessfull                => was_successfull := false ;
  9502.                                              end_an_entire_document ;
  9503.         when print_in_to_out.users_requested_abort => end_output ( true ) ;
  9504.                                              end_an_entire_document ;
  9505.                                              was_successfull := true ;
  9506.                                              printout_completed := true ;
  9507.         when print_out.fatal_output_error => end_output ( false ) ;
  9508.                                              end_an_entire_document ;
  9509.                                              was_successfull := false   ;
  9510.                                              printout_completed := true ;
  9511.       end try_printing ;
  9512.    
  9513.       procedure err( s : string ) is
  9514.       begin
  9515.         close_print_work ;
  9516.         text_io.new_line;
  9517.         text_io.new_line;
  9518.         text_io.put_line( "Exception: " & s ) ;
  9519.         text_io.new_line;
  9520.         text_io.new_line;
  9521.         text_io.put     ( "  Type <space> to continue.... ");
  9522.         wait_for_character(' ');
  9523.       end err ;
  9524.        
  9525.     begin -- text_formatter 
  9526.       print_package_initialize ; -- find out the type of printer attached
  9527.       Initial_Environment.printer_brand       := permanent_printer   ;
  9528.       Initial_Environment.printer_accessories := printer_accessories ;
  9529.       formatter_entry_input_file_name      := source_file ;
  9530.       formatter_entry_output_file_name     := destination_file ;
  9531.       formatter_requested_input_file_name  := source_file ;
  9532.       formatter_requested_output_file_name := destination_file ;
  9533.       if formatter_requested_input_file_name /= no_file then
  9534.         -- if we can't confirm the entry parameters, then fall through
  9535.         -- to the loop underneath
  9536.         try_printing( was_successfull ) ;
  9537.       else
  9538.         loop
  9539.           get_options ( please_quit ) ;
  9540.         exit when please_quit ;
  9541.           try_printing ( was_successfull ) ;
  9542.         end loop ;
  9543.       end if ;
  9544.       close_print_work ;
  9545.     exception
  9546.       -- when user_abort        => null ;
  9547.       when constraint_error  => err("Constraint Error");
  9548.       when numeric_error     => err("Numeric Error");
  9549.       when program_error     => err("Program Error");
  9550.       when storage_error     => err("Storage Error");
  9551.       when tasking_error     => err("Tasking Error");
  9552.       when others            => err("Unknown Error");
  9553.     end text_formatter ;
  9554.      
  9555.   begin -- print_main ;
  9556.     null ;
  9557.   end print_main ;
  9558.    
  9559.   --$$$- PRNTMAIN
  9560.  
  9561. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9562. --print
  9563. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9564.  
  9565.   --$$$+ PRINT
  9566.  
  9567.   with crt_customization ;
  9568.   with Wordp_Globals     ;
  9569.   with printer_globals   ;
  9570.   with print_main        ;
  9571.    
  9572.   procedure print is
  9573.   begin 
  9574.     print_main.text_formatter ( wordp_globals.no_file , 
  9575.                                 wordp_globals.no_file , 
  9576.                                 printer_globals.default_environment ) ;
  9577.     crt_customization.crt.do_crt(crt_customization.crt.program_termination);
  9578.   end print ;
  9579.    
  9580.   --$$$- PRINT
  9581.  
  9582. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9583. --prntfont
  9584. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9585.  
  9586.   --$$$+ PRNTFONT
  9587.    
  9588.   --
  9589.   -- File 0xx
  9590.   --
  9591.   -- Formatter Written By Robert S. Cymbalski
  9592.   --                      Science Applications International Corporation
  9593.   --                      Energy Systems Group
  9594.   --                      Ada Software Development Project Team
  9595.   --                      2280 U.S. Highway 19 North, Suite 120
  9596.   --                      Clearwater, Florida  33575
  9597.   --
  9598.   -- Print Routines Revised from text Copyright (c) 1984 , R.S.Cymbalski
  9599.   --
  9600.   
  9601.   with direct_io          ;
  9602.    
  9603.   with text_io            ;
  9604.   use  text_io            ;
  9605.   -- use integer_io       ; -- from wicat
  9606.    
  9607.   with string_library  ;
  9608.   use  string_library  ;
  9609.    
  9610.   with crt_customization ;
  9611.   use  crt_customization ;
  9612.   use  crt                    ;
  9613.   use  editor_customization   ;
  9614.    
  9615.   with crt_windows     ;
  9616.   use  crt_windows     ;
  9617.    
  9618.   with Wordp_Globals   ;
  9619.   use  Wordp_Globals   ;
  9620.  
  9621.   with printer_globals    ;
  9622.   use  printer_globals    ;
  9623.    
  9624.   Package Print_Font_Package is
  9625.      
  9626.     subtype data_file_name is ascii_text_file_name ;
  9627.      
  9628.     procedure ADD_TYPE_FONT( NEW_TYPE_FONT_FILE : in ASCII_TEXT_FILE_NAME ;
  9629.                              FONT_FILE          : in out Data_FILE_NAME );
  9630.                              -- in out because it updates to complete name
  9631.       -- This tool adds new type font definitions to the text formatter's 
  9632.       -- font table.  It is for use by the system's manager to define new
  9633.       -- fonts when new device capabilities are added at a site.  
  9634.       -- 
  9635.       -- This routine to be implemented later, for now, use the menu...
  9636.       -- given in font_options 
  9637.    
  9638.     Procedure Font_Options ;
  9639.       -- allow a menu driven selection of appropriate options
  9640.        
  9641.   end Print_Font_Package ;
  9642.      
  9643.   Package body Print_Font_Package is
  9644.      
  9645.     package Font_IO is new direct_io( Font_Type ) ;
  9646.        
  9647.     package int_io is new integer_io(integer) ;         -- not for wicat
  9648.     use int_io ;                                        -- not for wicat
  9649.        
  9650.     Total_Font_Numbers : constant integer := 20 ;
  9651.      
  9652.     ASCII_Font_Definition_File : text_io.file_type ;
  9653.     Font_Output_File : Font_IO.file_type ;
  9654.     Display_Status_Output_File : text_io.file_type ;
  9655.    
  9656.     print_name : constant string := "PRINTER:" ;
  9657.     cons_name  : constant string := "CONSOLE:" ;
  9658.     Show_Processing_Status : constant boolean := false ;
  9659.      
  9660.     Blank_Font_Name : constant Font_Name_Type := "                         " ;
  9661.      
  9662.     subtype Line_Place is Integer range 0 .. 200 ; 
  9663.     in_line : string ( Line_Place range 1 .. 200 ) ;
  9664.     line_length : Line_Place ;
  9665.     double_widths : boolean ;
  9666.     no_maps : map_array ;
  9667.      
  9668.     procedure put_a_line is
  9669.     begin
  9670.       crt_windows.put( ascii.cr ) ;
  9671.     end ;
  9672.      
  9673.     procedure put_a_line ( s : in string ) is
  9674.     begin
  9675.       crt_windows.put(s);
  9676.       crt_windows.put(ascii.cr);
  9677.     end ;
  9678.      
  9679.     Procedure Font_Initialization ( Print_Font : in out Font_Type ) is
  9680.       -- initialize the Print_Font record values
  9681.       temp_str : a_map_string ;
  9682.     begin 
  9683.       Print_Font.Name                         := Blank_Font_Name ;
  9684.       Print_Font.Number                       := 0 ;
  9685.       Print_Font.vertical_points_per_inch     := 0 ;
  9686.       Print_Font.horizontal_points_per_inch   := 0 ;
  9687.       Print_Font.Font_Width := 0 ;
  9688.       Print_Font.Font_Height:= 0 ;
  9689.       for ind in extended_character loop
  9690.         -- set each character's width and hammer intensity to 0
  9691.         Print_Font.width(ind) := 0 ;
  9692.         Print_Font.hammer_intensity(ind) := 0 ;
  9693.       end loop ;
  9694.       temp_str(2) := extended_character ( 0 ) ;
  9695.       temp_str(3) := extended_character ( 0 ) ;
  9696.       for ind in 0 .. 127 loop
  9697.         -- map each character to itself
  9698.         temp_str(1) := extended_character(ind) ; 
  9699.         Print_Font.map_string(ind) := temp_str ;
  9700.       end loop ;
  9701.       no_maps := Print_Font.Map_String ;
  9702.       -- No_Maps is an item which is a standard one to one mapping....
  9703.       -- we compare before saving to check to see if that has been
  9704.       -- modified...
  9705.       Print_Font.Mappings_Necessary := false ;
  9706.     end ;
  9707.      
  9708.     procedure put_font( Print_Font : in out Font_Type ;
  9709.                         RecN       : in integer       ) is
  9710.     begin
  9711.       Font_IO.write(Font_Output_File,Print_Font,font_io.positive_count(recn));
  9712.     end put_font ;
  9713.      
  9714.     procedure get_font( Print_Font : in out Font_Type ;
  9715.                         RecN       : in integer       ) is
  9716.     begin
  9717.       Font_IO.Read(Font_Output_File,Print_Font,font_io.positive_count(recn));
  9718.     end get_font ;
  9719.      
  9720.     Procedure CHECK_Font_FILE_EXISTS is
  9721.       -- check if Font_file exists , if not create a new Font_file
  9722.       -- in any case, open the font output file 
  9723.       Print_font : Font_Type ;
  9724.     begin
  9725.       If not file_exists( Font_File ) then
  9726.         -- need to create it
  9727.         put_a_line ;
  9728.         put_a_line ;
  9729.         crt_windows.put("  Creating The Font File """ ) ;
  9730.         crt_windows.put( Font_File ) ;
  9731.         crt_windows.put('"');
  9732.         put_a_line ;
  9733.         put_a_line ;
  9734.         Font_Initialization( Print_Font ) ;
  9735.         crt_windows.put(':');
  9736.         Font_IO.create ( Font_Output_File , Font_IO.out_file , Font_file ) ;
  9737.         crt_windows.put(':');
  9738.         for fontnum in 1 .. Total_Font_Numbers loop
  9739.           Print_Font.Number := fontnum ;
  9740.           put_font( Print_Font , fontnum ) ;
  9741.         end loop ;
  9742.         crt_windows.put(':');
  9743.         Font_IO.close ( Font_Output_File ) ;
  9744.       end if ;
  9745.       Font_IO.open ( Font_Output_File , Font_IO.inout_file , Font_file ) ;
  9746.     end ;
  9747.        
  9748.     Procedure PAUSE is
  9749.       charin:character ;
  9750.     begin
  9751.       crt_windows.put(" Enter Space to Continue ");
  9752.       charin := char_or_abort(' ' , ' ') ;
  9753.     end ;
  9754.      
  9755.     procedure read_next_line is
  9756.       -- read until non-empty line or else end of file 
  9757.     begin
  9758.       GET_LINE(ASCII_Font_Definition_File , in_line , line_length ) ;
  9759.     end;
  9760.      
  9761.     Procedure SCAN ( char       : in     character        ; 
  9762.                      place      : in out line_place       ;
  9763.                      ok_to_fail : in     boolean := false ) is
  9764.       -- search through in_line for given char starting at place postion 
  9765.       -- and returning found position in place
  9766.       found : boolean ;
  9767.     begin
  9768.       found := false ;
  9769.       while (not found) and (place <= line_length) loop
  9770.         if in_line(place) = char then
  9771.           found := true ;
  9772.         else
  9773.           place := place + 1 ;
  9774.         end if ;
  9775.       end loop ;
  9776.       If not Found then
  9777.         place := 0 ;
  9778.         if not ok_to_fail then 
  9779.           crt_windows.put("*** error - character '") ;
  9780.           crt_windows.put(char) ;
  9781.           put_a_line("' was not found in the line being processed : ") ;
  9782.           for posn in 1 .. line_length loop
  9783.             crt_windows.put( in_line(posn) ) ;
  9784.           end loop ;
  9785.           put_a_line ;
  9786.           put_a_line ;
  9787.         end if ;
  9788.       end if;
  9789.     end ;
  9790.    
  9791.     Procedure  PAST_SPACES ( place : in out Line_Place ) is
  9792.       -- move place in in_line past the preceeding spaces
  9793.       -- leaving place at the first non-space
  9794.     begin
  9795.       while ( in_line(place) = ' ' ) and ( place < line_length ) loop
  9796.         place := place + 1 ;
  9797.       end loop ;
  9798.     end ;
  9799.            
  9800.     Procedure Chars_To_Num ( Place : in out Line_Place ;
  9801.                              New_Number : out Integer ) is
  9802.       -- change the following characters in in_line to their 
  9803.       -- integer value
  9804.       num , char_value : integer ;
  9805.     begin
  9806.       past_spaces ( place ) ;
  9807.       num := 0 ;
  9808.       while ( in_line(place) >= '0' and in_line(place) <= '9' )
  9809.       and ( place <= line_length )  loop
  9810.         char_value := character'pos(in_line(place)) 
  9811.                     - character'pos('0') ;
  9812.         num := ( num * 10 ) + char_value ;
  9813.         place := place + 1 ;
  9814.       end loop ;
  9815.       New_Number := Num ;
  9816.     end ;
  9817.              
  9818.     Procedure PROCESS_MAPPINGS( Print_Font : in out Font_Type )  is
  9819.        
  9820.       char1 , char2 , char3 , char4 : character ;
  9821.       num1 , num2 , num3 , num4 : integer ;
  9822.       place : Line_Place ;
  9823.          
  9824.       Procedure INITIALIZE_VARS is 
  9825.       begin
  9826.         num1 := 0 ;
  9827.         num2 := 0 ;
  9828.         num3 := 0 ;
  9829.         num4 := 0 ;
  9830.         char1 := ascii.nul ;
  9831.         char2 := ascii.nul ;
  9832.         char3 := ascii.nul ;
  9833.         char4 := ascii.nul ;
  9834.       end ;
  9835.        
  9836.       Procedure PROCESS_LINE is
  9837.          
  9838.         Function READ_CHAR return character is
  9839.           -- return the current character in in_line and update the place
  9840.           return_char : character ;
  9841.         begin
  9842.           -- move past " before the character
  9843.           place := place + 1 ;
  9844.           return_char := in_line(place) ;
  9845.           -- move place past " after character
  9846.           place := place + 2 ;
  9847.           return return_char ;
  9848.         end ;
  9849.            
  9850.         Procedure CHECK_CORRES( numb : in integer ; 
  9851.                                 char : in out character ) is
  9852.           -- check to make sure the number correspond to its
  9853.           -- associated character
  9854.            
  9855.         begin
  9856.           if (char /= ascii.nul) and ( numb /= 0 ) then
  9857.             if character'val(numb) /= char then
  9858.               -- error in correspondance
  9859.               skip_line;
  9860.               crt_windows.put("*** ASCII") ;
  9861.               crt_windows.put(num1 , 4 ) ;
  9862.               crt_windows.put(" has illegal correspondence of") ;
  9863.               crt_windows.put(numb , 4 );
  9864.               crt_windows.put(" to");
  9865.               crt_windows.put('"') ;
  9866.               crt_windows.put(char) ;
  9867.               crt_windows.put('"') ;
  9868.               put_a_line ( "***");
  9869.             end if ;
  9870.           elsif (char = ascii.nul) then
  9871.             -- no character was in the input file for the 
  9872.             -- associated number so find that character value
  9873.             char := character'val(numb) ;
  9874.           -- else (numb = 0 and char /= ascii.nul)
  9875.           --   character value already in char
  9876.           end if ;
  9877.         end ;
  9878.        
  9879.         function e ( c : character ) return extended_character is
  9880.         begin
  9881.           return extended_character ( character'pos ( c ) ) ;
  9882.         end e ;
  9883.          
  9884.         Procedure DO_MAP is 
  9885.           char_temp : character ;
  9886.           inside_quote : boolean := false ;
  9887.         begin
  9888.           -- form the map_string entry for num1 
  9889.           check_corres(num2 , char2 ) ;
  9890.           Print_Font.map_string(num1)(1) := e ( char2 ) ;
  9891.           if (num3 /= 0) or (char3 /= ascii.nul) then
  9892.             check_corres(num3 , char3) ;
  9893.             Print_Font.map_string(num1)(2) := e ( char3 ) ;
  9894.             if (num4 /= 0) or (char4 /= ascii.nul) then
  9895.               check_corres(num4 , char4) ;
  9896.               Print_Font.map_string(num1)(3) := e ( char4 ) ;
  9897.             end if ;
  9898.           end if ;
  9899.           if Show_Processing_Status then
  9900.             crt_windows.put(" ASCII : ");
  9901.             crt_windows.put(num1 , 3 );
  9902.             if num1 >= 32 and num1 <= 126 then
  9903.               crt_windows.put(" '");
  9904.               crt_windows.put( character'val( num1 ) ) ;
  9905.               crt_windows.put("'");
  9906.             end if ;
  9907.             crt_windows.put("  Maps to : ");
  9908.             for i in 1 .. 3 loop
  9909.               if Print_Font.map_string(num1)(i) in 32 .. 126 then
  9910.                 -- is just a character...
  9911.                 if not inside_quote then
  9912.                   if i > 1 then
  9913.                     crt_windows.put(" & ");
  9914.                   end if ;
  9915.                   crt_windows.put('"');
  9916.                   inside_quote := true ;
  9917.                 end if ;
  9918.                 crt_windows.put(character'val(Print_Font.map_string(num1)(i))) ;
  9919.               else
  9920.                 if inside_quote then
  9921.                   crt_windows.put('"');
  9922.                   inside_quote := false ;
  9923.                 end if ;
  9924.                 if Print_Font.map_string(num1)(i) > 0 then
  9925.                   if i > 1 then crt_windows.put(" & "); end if ;
  9926.                   crt_windows.put('#');
  9927.                   crt_windows.put(Print_Font.map_string(num1)(i)) ;
  9928.                 end if ;
  9929.               end if ;
  9930.             end loop ;
  9931.             if inside_quote then
  9932.               crt_windows.put('"');
  9933.             end if ;
  9934.           end if;
  9935.         end ;
  9936.                
  9937.         Procedure PROCESS_HAMMER_AND_WIDTH is
  9938.           -- obtain the hammer_intensity and width from in_line
  9939.         begin
  9940.           chars_to_num ( place , Print_Font.hammer_intensity(num1) ) ;
  9941.           chars_to_num ( place , Print_Font.width(num1)            ) ;
  9942.           if double_widths then
  9943.             Print_Font.width(num1) := Print_Font.width(num1) * 2 ;
  9944.           end if ;
  9945.           if Show_Processing_Status then
  9946.             crt_windows.put( "   Intensity : ");
  9947.             crt_windows.put(Print_Font.hammer_intensity(num1) , 2 ) ;
  9948.             crt_windows.put( "   Width : ") ;
  9949.             crt_windows.put(Print_Font.width(num1) , 2 );
  9950.             end if;
  9951.         end ;
  9952.            
  9953.       begin -- process_line
  9954.         place := 1 ;
  9955.         chars_to_num ( place , num1 ) ;
  9956.         past_spaces(place) ;
  9957.         if in_line(place) = '/' then
  9958.           -- skip past value between the /s
  9959.           place := place + 1 ;
  9960.           scan ( '/' , place ) ;
  9961.           place := place + 1 ;
  9962.         else
  9963.           char1 := read_char ;
  9964.         end if ;
  9965.         past_spaces(place) ;
  9966.         if in_line(place) /= '"' then
  9967.           chars_to_num ( place , num2 ) ;
  9968.           if in_line(place) = '/' then
  9969.             place := place + 1;
  9970.             chars_to_num ( place , num3 ) ;
  9971.             if in_line(place) = '/' then
  9972.               place := place + 1;
  9973.               chars_to_num ( place , num4 ) ;
  9974.             end if ;
  9975.           end if ;
  9976.           past_spaces(place) ;
  9977.         end if ;
  9978.         if in_line(place) = '"' then
  9979.           char2 := read_char ;
  9980.           past_spaces(place) ;
  9981.           if in_line(place) = '"' then
  9982.             char3 := read_char ;
  9983.             past_spaces(place) ;
  9984.             if in_line(place) = '"' then
  9985.               char4 := read_char ;
  9986.             end if ;
  9987.           end if ;
  9988.         end if ;
  9989.         do_map ;
  9990.         past_spaces(place) ;
  9991.         process_hammer_and_width ;
  9992.         if Show_Processing_Status then
  9993.           put_a_line ;
  9994.         end if ;
  9995.       end ;  -- process_line
  9996.        
  9997.     begin -- process_mappings 
  9998.       -- First, we need to move to a good line....
  9999.       loop
  10000.       exit when end_of_file( ascii_font_definition_file ) ;
  10001.         read_next_line ;
  10002.         if line_length > 1 then
  10003.           place := 1 ;
  10004.           scan( '3' , place , true ) ; -- looks for 1st digit in 32 
  10005.       exit when place > 0 ;
  10006.         end if ;
  10007.       end loop ;
  10008.       loop
  10009.       exit when line_length <= 1 ;
  10010.         initialize_vars ;
  10011.         process_line ;
  10012.         read_next_line ;
  10013.       end loop ;
  10014.       Print_Font.Mappings_Necessary := Print_Font.Map_String /= No_Maps ;
  10015.       -- If Map_String has changed, then mappings are necessary
  10016.     end ; -- process_mappings 
  10017.        
  10018.     Procedure READIN_Print_Font_INFORMATION is
  10019.       Print_Font : Font_Type ;
  10020.       New_File_Name : Ascii_Text_File_Name ;
  10021.       ok : boolean ;
  10022.    
  10023.       function get_input_file_name return ascii_text_file_name is
  10024.         ok : boolean ;
  10025.         requested_source_file : ascii_text_file_name ;
  10026.       begin
  10027.         loop
  10028.           clear_window( master_window ) ;
  10029.           goto_line_column   ( master_window ,  5 , 1 ) ;
  10030.           crt_windows.put(
  10031.                 "  Enter Font Input File Name ( or <return> to abort ) => ") ;
  10032.           requested_source_file := 
  10033.                           get_input_filename_or_return ;
  10034.           if requested_source_file = no_file then
  10035.             ok := true ;
  10036.           elsif requested_source_file( 1 ) = ascii.esc then
  10037.             -- an error, the file name did not exist
  10038.             error(" File Name """ & compress(requested_source_file
  10039.                      ( 2 .. requested_source_file'length ) )
  10040.                                 & """ is invalid." ,
  10041.                    not_fatal_error , operator_wait , short_beep ) ;
  10042.           elsif not file_exists ( requested_source_file ) then
  10043.             -- an error, the file name did not exist
  10044.             error(" File """ & compress(requested_source_file
  10045.                      ( 2 .. requested_source_file'length ) )
  10046.                                 & """ does not exist." ,
  10047.                    not_fatal_error , operator_wait , short_beep ) ;
  10048.           else
  10049.             ok := true ; -- because it does not exist...
  10050.           end if ;
  10051.         -- need to set the default environment
  10052.         exit when ok ;
  10053.         end loop ;
  10054.         return requested_source_file ;
  10055.       end get_input_file_name ;
  10056.        
  10057.       Procedure Get_Font_Name_And_Points_Per_Inch(Print_Font : in out 
  10058.                                                                Font_Type) is
  10059.         otplace : integer ;
  10060.         place   : Line_Place ;
  10061.         num : integer ;
  10062.         char_value : integer ;
  10063.       begin
  10064.         -- get the print Font name from in_line found between the "s 
  10065.         loop
  10066.           read_next_line ;
  10067.           place := 1 ;
  10068.           scan ( '"' , place , true ) ;
  10069.         exit when end_of_file( ascii_font_definition_file ) or place > 0 ;
  10070.         end loop ;
  10071.         if place > 0 then
  10072.           place := place + 1 ;
  10073.           otplace := 1 ;
  10074.           while in_line(place) /= '"' loop
  10075.             Print_Font.name(otplace) := in_line(place) ;
  10076.             place := place + 1 ;
  10077.             otplace := otplace + 1 ;
  10078.           exit when otplace > Font_Name_Type'Last ;
  10079.           end loop ;
  10080.           -- store the length of the name 
  10081.           -- if Show_Processing_Status then
  10082.             put_a_line ;
  10083.             put_a_line ;
  10084.             crt_windows.put(" Font Name = """);
  10085.             crt_windows.put(Print_Font.Name);
  10086.             put_a_line("""");
  10087.           -- end if ;
  10088.           -- get the points per inch for the Print_Font , found after 
  10089.           -- the = in in_line
  10090.           scan ( '=' , place ) ;
  10091.           place := place + 1 ;
  10092.           chars_to_num ( place , num ) ;
  10093.           Print_Font.horizontal_points_per_inch := num ;
  10094.           Print_Font.Font_Width := num / 10 ; -- font width is 1/10"
  10095.           scan ( '=' , place ) ;
  10096.           place := place + 1 ;
  10097.           chars_to_num ( place , num ) ;
  10098.           Print_Font.Vertical_Points_Per_Inch   := num ;
  10099.           read_next_line ;
  10100.           place := 1 ;
  10101.           scan ( '=' , place ) ;
  10102.           place := place + 1 ;
  10103.           chars_to_num ( place , num ) ;
  10104.           Print_Font.Number := num ;
  10105.           -- if Show_Processing_Status then
  10106.             crt_windows.put(" Horizontal Points Per Inch = ") ;
  10107.             crt_windows.put(Print_Font.Horizontal_points_per_inch) ;
  10108.             put_a_line ;
  10109.             crt_windows.put(" Vertical Points Per Inch   = ") ;
  10110.             crt_windows.put(Print_Font.Vertical_points_per_inch) ;
  10111.             put_a_line ;
  10112.             crt_windows.put(" Font Number                = ");
  10113.             crt_windows.put(Print_Font.Number);
  10114.             put_a_line ;
  10115.             put_a_line ;
  10116.           -- end if ;
  10117.           -- now working double_widths
  10118.           scan ( '*' , place , true ) ;
  10119.           double_widths := place /= 0 ;
  10120.           -- if a '*' is found, the double the widths when they are read in
  10121.         end if ;
  10122.       end ;
  10123.        
  10124.       Procedure SAVE_DATA ( Print_Font : in out Font_Type ) is
  10125.         -- save data on print Font in Font_file checking first if the 
  10126.         -- print Font is already in the file and if so storing the new
  10127.         -- data over the old data
  10128.         rec_number : Integer := 1 ;
  10129.         cur_Font : Font_Type ;
  10130.         ok : boolean ;
  10131.       begin
  10132.         ok := false ;
  10133.         -- search through the file to see if print Font is already in file
  10134.         loop
  10135.           crt_windows.put('/');
  10136.           get_font( Cur_Font , Rec_Number ) ;
  10137.           if Print_Font.name = cur_Font.name then
  10138.             -- put at current position where print Font was already in file
  10139.             put_font( Cur_Font , Rec_Number ) ;
  10140.             if Show_Processing_Status then
  10141.               put_a_line(" saving data in file ");
  10142.               put_a_line(" storing print Font over old Font data in file");
  10143.               put_a_line ;
  10144.               put_a_line ;
  10145.             end if ;
  10146.             ok := true ;
  10147.           else
  10148.             rec_number := rec_number + 1 ;
  10149.           end if ;
  10150.           exit when ( cur_Font.name = blank_Font_Name ) or ok ;
  10151.         end loop;
  10152.         if not ok then
  10153.           -- put at end of file and make new end
  10154.           put_font( Print_Font , Rec_Number - 1 ) ;
  10155.           Print_Font.name := Blank_Font_Name ;
  10156.           put_font( Print_Font , Rec_Number     ) ;
  10157.           if Show_Processing_Status then
  10158.             crt_windows.put(" saving data at end of file -");
  10159.             put_a_line(" print Font not already in file");
  10160.             put_a_line(" wrote new end to file ");
  10161.             put_a_line;
  10162.             put_a_line ;
  10163.           end if ;
  10164.         end if ;
  10165.       end ;
  10166.        
  10167.     begin -- readin_Print_Font_information 
  10168.       New_File_Name := Get_Input_File_Name ;
  10169.       If New_File_Name /= No_File then
  10170.         open_for_read( ASCII_Font_Definition_File , New_File_Name , Ok ) ;
  10171.         If Ok Then
  10172.           reset(ASCII_Font_Definition_File) ;
  10173.           while not end_of_file( ASCII_Font_Definition_File ) loop
  10174.             Font_Initialization(Print_Font) ;
  10175.             Get_Font_Name_And_Points_Per_Inch(Print_Font) ;
  10176.           exit when end_of_file( ascii_font_definition_file ) ;
  10177.             PROCESS_MAPPINGS(Print_Font) ;
  10178.             -- SAVE_DATA(Print_Font) ;
  10179.             put_font ( Print_Font , Print_Font.Number ) ;
  10180.           end loop ;
  10181.           close ( ASCII_Font_Definition_File ) ;
  10182.         end if ;
  10183.       end if ;
  10184.     end ;
  10185.      
  10186.     Procedure LIST_Font_NAMES ( go_to_printer : boolean ) is
  10187.       rec_num : Integer := 1 ;
  10188.       cur_Font : Font_Type ;
  10189.       linenum : integer := 1 ;
  10190.     begin
  10191.       if go_to_printer then
  10192.         open(Display_Status_Output_File , out_file , print_name ) ;
  10193.         for linn in 1 .. 6 loop
  10194.           new_line( display_status_output_file ) ;
  10195.           linenum := linenum + 1 ;
  10196.         end loop ;
  10197.       else
  10198.         clear_window(master_window);
  10199.         clear_prompt(master_window);
  10200.         open(Display_Status_Output_File , out_file , cons_name ) ;
  10201.       end if ;
  10202.       put_line(Display_Status_Output_File , 
  10203.                   " Number  Print Font Name              Points");
  10204.       new_line(Display_Status_Output_File) ;
  10205.       linenum := linenum + 2 ;
  10206.       for rec_num in 1 .. Total_Font_Numbers loop
  10207.         get_font( Cur_Font , rec_num ) ;
  10208.         if cur_Font.name /= Blank_Font_Name then
  10209.           put(Display_Status_Output_File , integer(rec_num) , 5 ) ;
  10210.           put(Display_Status_Output_File , "    ") ;
  10211.           put(Display_Status_Output_File , cur_Font.name ) ;
  10212.           put(Display_Status_Output_File , "    " ) ;
  10213.           put(Display_Status_Output_File,cur_Font.horizontal_points_per_inch,3);
  10214.           put(Display_Status_Output_File , "    " ) ;
  10215.           put(Display_Status_Output_File,cur_Font.vertical_points_per_inch, 3) ;
  10216.           new_line(Display_Status_Output_File)  ;
  10217.           linenum := linenum + 1 ;
  10218.         end if ;
  10219.       end loop ;
  10220.       if go_to_printer then
  10221.         while linenum <= 66 loop
  10222.           new_line ( display_status_output_file ) ;
  10223.           linenum := linenum + 1 ;
  10224.         end loop ;
  10225.       else
  10226.         for i in 1 .. 3 loop
  10227.           new_line(Display_Status_Output_File) ;
  10228.         end loop ;
  10229.       end if ;
  10230.       close ( Display_Status_Output_File ) ;
  10231.       new_line ;
  10232.       if not go_to_printer then
  10233.         pause ;
  10234.       end if ;
  10235.     end ;
  10236.      
  10237.     Procedure LISTFont ( Physical_Font_Number : integer ;
  10238.                           go_to_printer : boolean ) is 
  10239.        
  10240.       Print_Font : Font_Type ;
  10241.       linenum : integer ;
  10242.       print_line : integer := 1 ;
  10243.        
  10244.       Procedure DOHEADING is 
  10245.       begin
  10246.         if go_to_printer then
  10247.           for linn in 1 .. 6 loop
  10248.             new_line( display_status_output_file ) ;
  10249.             print_line := print_line + 1 ;
  10250.           end loop ;
  10251.         else
  10252.           new_line(Display_Status_Output_File ) ;
  10253.           new_line(Display_Status_Output_File ) ;
  10254.         end if ;
  10255.         put(Display_Status_Output_File , " Print Font Name = """ ) ;
  10256.         put(Display_Status_Output_File , Print_Font.name ) ;
  10257.         put(Display_Status_Output_File , """  Points=");
  10258.         put(Display_Status_Output_File , 
  10259.                     Print_Font.Horizontal_points_per_inch ) ;
  10260.         put(Display_Status_Output_File ,"  ");
  10261.         put(Display_Status_Output_File , 
  10262.                     Print_Font.Vertical_points_per_inch ) ;
  10263.         new_line(Display_Status_Output_File ) ;
  10264.         new_line(Display_Status_Output_File ) ;
  10265.         print_line := print_line + 2 ;
  10266.         put(Display_Status_Output_File , 
  10267.                     "ASCII  CHARACTER  MAP-ASCII  MAP-CHARACTER  ");
  10268.         put_line(Display_Status_Output_File , "HAMMER  WIDTH");
  10269.         new_line(Display_Status_Output_File) ;
  10270.         print_line := print_line + 2 ;
  10271.         linenum := 7 ;
  10272.       end ;
  10273.      
  10274.       Procedure SHOWLINE( c_num : in integer ) is 
  10275.       begin
  10276.         put(Display_Status_Output_File , "  " ) ;
  10277.         put(Display_Status_Output_File , c_num , 3 ) ;
  10278.         put(Display_Status_Output_File , "   """ ) ;
  10279.         put(Display_Status_Output_File , character'val(c_num)) ;
  10280.         put(Display_Status_Output_File , """   " ) ;
  10281.         put(Display_Status_Output_File , "   " ) ;
  10282.         put(Display_Status_Output_File , Print_Font.map_string(c_num)(1) ) ;
  10283.         put(Display_Status_Output_File , "        " ) ;
  10284.         put(Display_Status_Output_File , '"' ) ;
  10285.         put(Display_Status_Output_File , character'val( Print_Font.map_string(
  10286.                                                                  c_num)(1) ) ) ;
  10287.         put(Display_Status_Output_File , """          " ) ;
  10288.         put(Display_Status_Output_File , Print_Font.hammer_intensity(c_num) ) ;
  10289.         put(Display_Status_Output_File , "  " ) ;
  10290.         put(Display_Status_Output_File , Print_Font.width(c_num) ) ;
  10291.         new_line( Display_Status_Output_File ) ;
  10292.         print_line := print_line + 1 ;
  10293.       end ;
  10294.      
  10295.     begin
  10296.       if go_to_printer then
  10297.         open(Display_Status_Output_File , out_file , print_name ) ;
  10298.       else
  10299.         open(Display_Status_Output_File , out_file , cons_name ) ;
  10300.       end if ;
  10301.       get_font( Print_Font , Physical_Font_Number ) ;
  10302.       DOHEADING ;
  10303.       FOR CHARNUM in 32 .. 126 loop
  10304.         showline(charnum) ;
  10305.         linenum := linenum + 1 ;
  10306.         if go_to_printer then
  10307.           -- do printer line number work
  10308.           if print_line > 60 then
  10309.             while print_line < 67 loop
  10310.               new_line ( display_status_output_file ) ;
  10311.               print_line := print_line + 1 ;
  10312.             end loop ;
  10313.             print_line := 1 ;
  10314.             doheading ;
  10315.           end if ;
  10316.         elsif ( linenum > 24 ) then
  10317.           PAUSE ;
  10318.           DOHEADING ;
  10319.         end if ;
  10320.       end loop ;
  10321.       if go_to_printer then
  10322.         while print_line < 67 loop
  10323.           new_line ( display_status_output_file ) ;
  10324.           print_line := print_line + 1 ;
  10325.         end loop ;
  10326.       else
  10327.         for i in linenum .. 24 loop 
  10328.           new_line(Display_Status_Output_File) ;
  10329.         end loop ;
  10330.       end if ;
  10331.       close(Display_Status_Output_File) ;
  10332.       if not go_to_printer then
  10333.         pause ;
  10334.       end if ;
  10335.     end ;
  10336.      
  10337.     Procedure DELETE_Font( Fontnum : in integer ) is 
  10338.       index : integer ;
  10339.       Print_Font : Font_Type ;
  10340.     begin
  10341.       get_font( Print_Font , Fontnum ) ;
  10342.       if Print_Font.name = Blank_Font_Name then
  10343.         raise end_error ;
  10344.       end if ;
  10345.       clear_window( master_window ) ;
  10346.       clear_prompt( master_window ) ;
  10347.       goto_line_column ( master_window , 5 , 3 ) ;
  10348.       crt_windows.put(" Deleting """) ;
  10349.       crt_windows.put( Print_Font.Name ) ;
  10350.       crt_windows.put(""" which is Physical Font # ");
  10351.       crt_windows.put(Fontnum);
  10352.       index := Fontnum ;
  10353.       Loop 
  10354.         get_font( Print_Font , Index + 1 ) ;
  10355.       exit when Print_Font.name = blank_font_name ; 
  10356.         goto_line_column( master_window , 10 , 3 ) ;
  10357.         crt_windows.put( "Moving """) ;
  10358.         crt_windows.put( Print_Font.Name ) ;
  10359.         crt_windows.put(""" which was Physical Font # ");
  10360.         crt_windows.put(Index+1);
  10361.         crt_windows.put(" to Font # ");
  10362.         crt_windows.put(Index);
  10363.         Put_Font( Print_Font , Index ) ;
  10364.         index := index + 1 ;
  10365.       end loop ;
  10366.       -- Lastly, put end of file marker on...
  10367.       put_font( Print_Font , Index ) ;
  10368.       pause ;
  10369.     exception 
  10370.       when end_error => new_line ;
  10371.                         crt_windows.put(
  10372.                                      " no print Font exits with the number : ");
  10373.                         crt_windows.put( Fontnum ) ;
  10374.                         new_line ;
  10375.                         pause ;
  10376.     end ;
  10377.      
  10378.     procedure ADD_TYPE_FONT( NEW_TYPE_FONT_FILE : in ASCII_TEXT_FILE_NAME ;
  10379.                              FONT_FILE          : in out Data_FILE_NAME ) is
  10380.       -- This tool adds new type font definitions to the text formatter's 
  10381.       -- font table.  It is for use by the system's manager to define new
  10382.       -- fonts when new device capabilities are added at a site.  
  10383.     begin -- add_type_font 
  10384.       check_font_file_exists ;
  10385.        
  10386.        
  10387.       Font_IO.close(font_output_file ) ;
  10388.     end add_type_font ;
  10389.      
  10390.     procedure err( s : string ) is
  10391.       c : character ;
  10392.     begin
  10393.       put_a_line;
  10394.       put_a_line;
  10395.       crt_windows.put( "Exception: " & s ) ;
  10396.       put_a_line;
  10397.       put_a_line;
  10398.       put_a_line;
  10399.       crt_windows.put     ( "  Type <space> to continue.... ");
  10400.       c := char_or_abort( ' ' , ' ' ) ;
  10401.     end err ;
  10402.    
  10403.     procedure print_all is
  10404.       -- print a copy of all information ...
  10405.       Print_Font : Font_Type ;
  10406.     begin -- print_all
  10407.       List_Font_Names ( True ) ;
  10408.       for fontnum in 1 .. total_font_numbers loop
  10409.         get_font ( Print_Font , fontnum ) ;
  10410.         If Print_Font.Name /= Blank_Font_Name then
  10411.           -- we want to show it...
  10412.           listfont( fontnum , true ) ;
  10413.         end if ;
  10414.       end loop ;
  10415.     end print_all ;
  10416.      
  10417.     Procedure Font_Options is
  10418.       -- allow a menu driven selection of appropriate options
  10419.       User_Option : character ;
  10420.       Physical_Font_Number : Font_Number ;
  10421.     begin -- Font_Options
  10422.       check_font_file_exists ;
  10423.       loop 
  10424.         clear_window( master_window ) ;
  10425.         clear_prompt( master_window ) ;
  10426.         goto_line_column( master_window , 2 , 1 ) ;
  10427.         put_a_line("      Print Font Information Set-up and Listing Program ") ;
  10428.         put_a_line ;
  10429.         put_a_line("        I : Input new information on Print Fonts ");
  10430.         put_a_line("        P : Print Information on a Font ");
  10431.         put_a_line("        L : List  Information on a Font ");
  10432.         put_a_line("        V : View Print Font List ");
  10433.         put_a_line("        Y : Print Print Font List ");
  10434.         -- put_a_line("        D : Delete a Specific Font ");
  10435.         put_a_line("        C : Print Complete List of All Information ");
  10436.         put_a_line;
  10437.         put_a_line("        Q : Quit ");
  10438.         put_a_line;
  10439.         crt_windows.put( "      Enter Option ? ") ;
  10440.         User_Option:=char_or_abort('Q', 'I' , 'P' , 'L' , 'V' , 'Y' , 'Q'
  10441.                                       -- , 'D'
  10442.                                       , 'C' );
  10443.         if User_Option /= 'Q' then
  10444.           if User_Option = 'D' or User_Option = 'L' or User_Option = 'P' then
  10445.             put_a_line ;
  10446.             crt_windows.put(" Enter Number of Print Font => ") ;
  10447.             physical_font_number := get_number( 0 , 0 , 1 , 50 , 2 , 0 ) ;
  10448.           end if ;
  10449.           case User_Option is
  10450.             when 'V' | 'Y' => LIST_Font_NAMES(User_Option = 'Y' )  ;
  10451.             when 'I' => READIN_Print_Font_INFORMATION ;
  10452.             when 'P' | 'L' => LISTFont(Physical_Font_Number,
  10453.                                         User_Option = 'P' ) ;
  10454.             when 'D' => DELETE_Font(Physical_Font_Number) ;
  10455.             when 'C' => Print_All ;
  10456.             when others => null ;
  10457.           end case ;
  10458.         end if ;
  10459.         exit when User_Option = 'Q' ;
  10460.       end loop ;
  10461.       Font_IO.close( font_output_file );
  10462.     exception
  10463.       -- when user_abort        => null ;
  10464.       when constraint_error  => err("Constraint Error");
  10465.       when numeric_error     => err("Numeric Error");
  10466.       when program_error     => err("Program Error");
  10467.       when storage_error     => err("Storage Error");
  10468.       when tasking_error     => err("Tasking Error");
  10469.       when others            => err("Unknown Error");
  10470.     end Font_Options ;
  10471.        
  10472.   begin -- Print_Font_Package
  10473.     null ;
  10474.   end Print_Font_Package ;
  10475.  
  10476.   --$$$- PRNTFONT
  10477.  
  10478. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10479. --font
  10480. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10481.  
  10482.   --$$$+ FONT
  10483.  
  10484.   with crt_customization ;
  10485.   use  crt_customization ;
  10486.    
  10487.   with print_font_package ;
  10488.   use  print_font_package ;
  10489.    
  10490.   procedure font is
  10491.   begin 
  10492.     font_options ;
  10493.     crt.do_crt(crt.program_termination);
  10494.   end font ;
  10495.    
  10496.   --$$$- FONT
  10497.  
  10498.  
  10499.