!++
! FILENAME: PRINT_BUFFER.TPU
! FUNCTION: This file contains procedures for filtering non printable
!           characters from a buffer and for the printing of buffers.
! AUTHOR:   Steven K. Shapiro, (C) Copyright SKS Enterprises, Austin TX.
!                                  All Rights Reserved.
!
!           The format, structure and contents of this file are the sole
!           property  of Steven K. Shapiro  and are  copyrighted to  SKS
!           Enterprises, Austin Texas.
!
!           The information may be freely distributed, used and modified
!           provided  that the  information in this  header block is not
!           changed, altered, disturbed or modified in any way.
!
! DATE:     25-AUG-1987 Original.
! HISTORY:  current.
! CONTENTS:
!           eve_print_buffer
!           eve$translate_controls (char)
!           eve$search_controls (this_buffer)
!           ep$find_xlate_controls (this_buffer)
!           ep$find_xlate_multinationals (this_buffer)
!           eve_filter_buffer
!           eve_print_select_range
!           ep$xlate_controls (char)
!           ep$xlate_multinationals (char)
!
!23456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H
!--
!*----------------------------------------------------------------------------*!

procedure print_buffer_module_ident 

  local file_date,
        module_vers;

  file_date := "-<( 29-DEC-1988 17:28:02.09 )>-";
  module_vers := substr(file_date,5,2) +
                 substr(file_date,8,3) +
                 substr(file_date,14,2) +
                 substr(file_date,17,5) ;

  return module_vers;

endprocedure;

!*----------------------------------------------------------------------------*!
!
! This procedure copies the current buffer to the translate buffer, translates
! non-printing control characters and DEC Multinational characters to readable
! character strings, writes the translate buffer to a file with the extension
! of .PNT, and submits the file to be printed.
!
procedure eve_print_buffer

local   this_informational,     ! Keyword for display of informational messages
        this_position,
        this_buffer,
        buffer_name,
        file_name,
        rbrack,
        filext,
        print_command,
        print_process;

    on_error
        if error = tpu$_createfail
        then
             message("Subprocess could not be created");
             return;
        endif;
    endon_error;

    if get_info (system, "informational")
    then
        this_informational := on;
    else
        this_informational := off;
    endif;
    set(informational,off);
    set(success,off);
    this_position := mark(none);
    this_buffer := current_buffer;

    if get_info(translate_buffer,"type") = UNSPECIFIED then
        translate_buffer := create_buffer ('translation');
        set (no_write, translate_buffer);
    endif;

    position (translate_buffer);
    erase (translate_buffer);
    copy_text (this_buffer);    ! Make a copy of the original buffer

    ep$find_xlate_controls(this_buffer); ! Translate control characters.

    position (beginning_of (translate_buffer));
!    if search (ep$multnat_char_pat, forward) <> 0
!    then
!       if eve$insist_y_n (
!           'This buffer contains Non-printable Multinational characters. ' +
!               'Translate them? ')
!       then
!           ! Translate multinational characters.
            ep$find_xlate_multinationals(this_buffer);
!       endif;
!    endif;

! Get the output file name from the original buffer and use it as the file
! name for the translated buffer.

    buffer_name := get_info(this_buffer,"name");
    file_name := get_info(this_buffer,"file_name");

! if no output file name then ask the user for one.

    if file_name = ""
    then
      file_name := read_line ("Enter a file name to write buffer " +
                   buffer_name + " or press RETURN to cancel: ");
      if file_name = ""
      then
        set (informational, this_informational);
        set(success,on);
        return;
      else
        if ( index(file_name,".") = 0 )
        then
          file_name := file_name + ".;";
        else
          if ( index(file_name,";") = 0 )
          then
            file_name := file_name + ";"
          endif;
        endif;
      endif;
    endif;

!    message("Input Filename =>"+file_name);

    if ( index(file_name,";") <> 0 )
    then
       rbrack := index(file_name,"]");
!       message("rbrack =>"+str(rbrack));
       filext := index(substr(file_name,rbrack+1,length(file_name)),".");
!       message("filext =>"+str(filext));
!       file_name := substr(file_name,1,index(file_name,";") - 1);
       file_name := substr(file_name,1,rbrack + filext);
    endif;

    file_name := file_name + "PNT";
!    message("Output Filename =>"+file_name);

! Set the output file on the original buffer
!  just in case it didn't have one.

!    set(output_file,this_buffer,file_name);
    set(output_file,translate_buffer,file_name);
    write_file(translate_buffer);

!    ask the user for the print command
!    print_command := read_line("Print command: ");

! if none returned set the default.
!    if print_command = ""
!    then
        print_command := "PRINT/QUEUE=SYS$PRINT/NOTIFY";
!    endif;

    print_command := print_command + " ";
    message(fao("Printing !AS with command !AS",buffer_name,print_command));
    print_process := create_process(message_buffer,"$set noon");
    send(print_command + file_name, print_process);

    delete(print_process);
    set (informational, this_informational);
    set (success, on);
    update(message_window);

    position(this_position);

    message("Output file saved in: "+file_name);

endprocedure;

!*----------------------------------------------------------------------------*!
!
! This procedure translates control characters to readable characters.
!
procedure eve$translate_controls (char)

! The backwards questions mark is the placeholder for control characters
! from ASCII(0) thru ASCII(31) on the VT2xx series of terminals
CASE char FROM ' ' TO ''

    [' '] : COPY_TEXT ('<NUL>');
    [''] : COPY_TEXT ('<SOH>');
    [''] : COPY_TEXT ('<STX>');
    [''] : COPY_TEXT ('<ETX>');
    [''] : COPY_TEXT ('<EOT>');
    [''] : COPY_TEXT ('<ENQ>');
    [''] : COPY_TEXT ('<ACK>');
    [''] : COPY_TEXT ('<BEL>');
    [''] : COPY_TEXT ('<BS>');
    [''] : COPY_TEXT ('<SO>');
    [''] : COPY_TEXT ('<SI>');
    [''] : COPY_TEXT ('<DLE>');
    [''] : COPY_TEXT ('<DC1>');
    [''] : COPY_TEXT ('<DC2>');
    [''] : COPY_TEXT ('<DC3>');
    [''] : COPY_TEXT ('<DC4>');
    [''] : COPY_TEXT ('<NAK>');
    [''] : COPY_TEXT ('<SYN>');
    [''] : COPY_TEXT ('<ETB>');
    [''] : COPY_TEXT ('<CAN>');
    [''] : COPY_TEXT ('<EM>');
    [''] : COPY_TEXT ('<SUB>');
    [''] : COPY_TEXT ('<ESC>');
    [''] : COPY_TEXT ('<FS>');
    [''] : COPY_TEXT ('<GS>');
    [''] : COPY_TEXT ('<RS>');
    [''] : COPY_TEXT ('<US>');
    [INRANGE, OUTRANGE] : COPY_TEXT (char);

endcase;
endprocedure

!*----------------------------------------------------------------------------*!
!
! This procedure controls the outer loop search for the special
! control characters that we want to view
!
procedure eve$search_controls (this_buffer)
local
    control_char_pat,
    control_char,
    char_to_translate;

! When the search fails we know that we have either hit the end of
! the buffer or there were no more special characters found.

on_error
   position (translate_buffer);
   return;
endon_error;

if get_info(translate_buffer,"type") = UNSPECIFIED then
    translate_buffer := create_buffer ('translation');
    set (no_write, translate_buffer);
endif;
control_char_pat := any (' ');

position (translate_buffer);
erase (translate_buffer);
copy_text (this_buffer);	! Make a copy of the original buffer
position (beginning_of (translate_buffer));

loop	! Find all occurrences
    control_char := search (control_char_pat, forward);
    position (control_char);
    char_to_translate := current_character;	! Save the character
    erase (control_char);			! then erase it
    eve$translate_controls (char_to_translate);	! Substitute the new text
endloop;

endprocedure

!*----------------------------------------------------------------------------*!

! This procedure locates the control characters in the transalate buffer that
! require translation and replaces them with printable strings.
!
procedure ep$find_xlate_controls (this_buffer)

local   control_char_pat,
        control_char,
        char_to_translate;

! When the search fails we know that we have either hit the end of
! the buffer or there were no more special characters found.

    on_error
        position (translate_buffer);
        return;
    endon_error;

    control_char_pat := any (' ');

    position (beginning_of (translate_buffer));

    loop        ! Find all occurrences
        control_char := search (control_char_pat, forward);
        position (control_char);
        char_to_translate := current_character; ! Save the character
        erase (control_char);                   ! then erase it
        eve$insert_text(ep$xlate_controls (char_to_translate)); ! and replace it
    endloop;

endprocedure

!*----------------------------------------------------------------------------*!
!
! This procedure locates the control characters in the transalate buffer that
! require translation and replaces them with printable strings.
!
procedure ep$find_xlate_multinationals (this_buffer)

local   multnat_char_pat,
        multinat_char,
        multnat_char,
        char_to_translate;

! When the search fails we know that we have either hit the end of
! the buffer or there were no more special characters found.

    on_error
        position (translate_buffer);
        return;
    endon_error;

    multinat_char := "" +
        "" +
        "";
    multnat_char_pat := any (multinat_char);

    position (beginning_of (translate_buffer));

    loop        ! Find all occurrences
        multnat_char := search (multnat_char_pat, forward);
        position (multnat_char);
        char_to_translate := current_character; ! Save the character
        erase (multnat_char);                   ! then erase it and replace
        eve$insert_text(ep$xlate_multinationals (char_to_translate)); ! it
    endloop;

endprocedure

!*----------------------------------------------------------------------------*!
!
! This procedure copies the current buffer to the translate buffer, translates
! non-printing control characters and DEC Multinational characters to readable
! character strings, and writes the translate buffer to a file with the
! extension of .FLT
!
procedure eve_filter_buffer

local   this_informational,     ! Keyword for display of informational messages
        this_position,
        this_buffer,
        buffer_name,
        file_name,
        rbrack,
        filext,
        translate_window,
        print_command,
        print_process;

    on_error
      return;
    endon_error;

    if get_info (system, "informational")
    then
        this_informational := on;
    else
        this_informational := off;
    endif;

    set(informational,off);
    set(success,off);
    this_position := mark(none);
    this_buffer := current_buffer;

    if get_info(translate_buffer,"type") = UNSPECIFIED then
        translate_buffer := create_buffer ('translation');
        set (no_write, translate_buffer);
    endif;

    translate_window := CREATE_WINDOW (1, 10, on);

    position (translate_buffer);
    erase (translate_buffer);
    copy_text (this_buffer);    ! Make a copy of the original buffer

    ep$find_xlate_controls(this_buffer); ! Translate control characters.

    position (beginning_of (translate_buffer));
    ep$find_xlate_multinationals(this_buffer);

! Get the output file name from the original buffer and use it as the file
! name for the translated buffer.

    buffer_name := get_info(this_buffer,"name");
    file_name := get_info(this_buffer,"file_name");

! if no output file name then ask the user for one.

    if file_name = ""
    then
      file_name := read_line ("Enter a file name to write buffer " +
                   buffer_name + " or press RETURN to cancel: ");
      if file_name = ""
      then
        set (informational, this_informational);
        set(success,on);
        POSITION (BEGINNING_OF (translate_buffer));  ! Move to buffer top
        eve_split_window;
        eve$set_status_line (translate_window);
        return;
      else
        if ( index(file_name,".") = 0 )
        then
          file_name := file_name + ".;";
        else
          if ( index(file_name,";") = 0 )
          then
            file_name := file_name + ";"
          endif;
        endif;
      endif;
    endif;

!    message("Input Filename =>"+file_name);

    if ( index(file_name,";") <> 0 )
    then
       rbrack := index(file_name,"]");
!       message("rbrack =>"+str(rbrack));
       filext := index(substr(file_name,rbrack+1,length(file_name)),".");
!       message("filext =>"+str(filext));
!       file_name := substr(file_name,1,index(file_name,";") - 1);
       file_name := substr(file_name,1,rbrack + filext);
    endif;

    file_name := file_name + "FLT";
!    message("Output Filename =>"+file_name);

! Set the output file on the original buffer
! just in case it didn't have one.

!    set(output_file,this_buffer,file_name);
    set(output_file,translate_buffer,file_name);
    write_file(translate_buffer);

    set (informational, this_informational);
    set (success, on);
    update(message_window);

    position(this_position);

    message("Output file saved in: "+file_name);

    POSITION (BEGINNING_OF (translate_buffer));  ! Move to buffer top
    eve_split_window;
    eve$set_status_line (translate_window);

endprocedure;

!*----------------------------------------------------------------------------*!
!
! This procedure will print a selected range. If there is no selected range
! active, it will inform the user and quit. It copies the current buffer to
! the translate buffer, translates non-printing control characters and DEC
! Multinational characters to readable character strings, and then submits it
! to be printed. The selected range is written to a file with the extension SEL.
!
procedure eve_print_select_range

local   this_informational,     ! Keyword for display of informational messages
        this_position,
        this_buffer,
        buffer_name,
        file_name,
        rbrack,
        filext,
        print_command,
        v_range,
	v_line,
	v_pos,
        print_process;

    on_error
        if error = tpu$_createfail
        then
             message("Subprocess could not be created");
             return;
        endif;
    endon_error;

    if get_info (system, "informational")
    then
        this_informational := on;
    else
        this_informational := off;
    endif;

    set(informational,off);
    set(success,off);
    this_position := mark(none);
    this_buffer := current_buffer;

    v_pos := mark(none);

    if (eve$x_select_position = 0)
    then
      message ("No select range active.");
      return;

!      v_range := create_range (beginning_of(current_buffer),
!                               end_of(current_buffer), none);
    else
      v_range := create_range (eve$x_select_position, mark(none), none);
    endif;

    if get_info(translate_buffer,"type") = UNSPECIFIED then
        translate_buffer := create_buffer ('translation');
        set (no_write, translate_buffer);
    endif;

    position (translate_buffer);
    erase (translate_buffer);

    copy_text (v_range);         ! Copy range into translation buffer.

    ep$find_xlate_controls(this_buffer); ! Translate control characters.

    position (beginning_of (translate_buffer)); ! Move back to beginning of buf.

    ep$find_xlate_multinationals(this_buffer); ! Translate multinational chars.

! Get the output file name from the original buffer and use it as the file
! name for the translated buffer.

    buffer_name := get_info(this_buffer,"name");
    file_name := get_info(this_buffer,"file_name");

    file_name := buffer_name;

!    message("Buffer Filename =>"+buffer_name);

! if no output file name then ask the user for one.

    if file_name = ""
    then
      file_name := read_line ("Enter a file name to write buffer " +
                   buffer_name + " or press RETURN to cancel: ");
      if file_name = ""
      then
        set (informational, this_informational);
        set(success,on);
        return;
      endif;
    endif;

    if ( index(file_name,".") = 0 )
    then
      file_name := file_name + ".;";
    else
      if ( index(file_name,";") = 0 )
      then
        file_name := file_name + ";"
      endif;
    endif;

    if ( index(file_name,";") <> 0 )
    then
       rbrack := index(file_name,"]");
!       message("rbrack =>"+str(rbrack));
       filext := index(substr(file_name,rbrack+1,length(file_name)),".");
!       message("filext =>"+str(filext));
!       file_name := substr(file_name,1,index(file_name,";") - 1);
       file_name := substr(file_name,1,rbrack + filext);
    endif;

    file_name := file_name + "SEL";

!    message("Output Filename =>"+file_name);

!   Set the output file on the original buffer
!   just in case it didn't have one.

    set(output_file,translate_buffer,file_name);
    write_file(translate_buffer);

    print_command := "PRINT/QUEUE=SYS$PRINT/NOTIFY ";

    message(fao("Printing !AS with command !AS",file_name,print_command));
    print_process := create_process(message_buffer,"$set noon");
    send(print_command + file_name, print_process);

    delete(print_process);
    set (informational, this_informational);
    set (success, on);
    update(message_window);

    position(this_position);

    message("Output file saved in: "+file_name);

endprocedure;

!*----------------------------------------------------------------------------*!

! This procedure returns a printable string for a non-printable control
! character.

procedure ep$xlate_controls (char)

    ! The backwards questions mark is the placeholder for many control
    ! characters from ASCII(0) thru ASCII(31) on the VT2xx series of terminals
    ! The checkerboard mark is the placeholder for most control characters
    ! from ASCII(0) thru ASCII(31) on the VT1xx series of terminals

    CASE char FROM ' ' TO ''

        [' '] : return ('<NUL>');     ! 00
        [''] : return ('<SOH>');     ! 01
        [''] : return ('<STX>');     ! 02
        [''] : return ('<ETX>');     ! 03
        [''] : return ('<EOT>');     ! 04
        [''] : return ('<ENQ>');     ! 05
        [''] : return ('<ACK>');     ! 06
        [''] : return ('<BEL>');     ! 07
        [''] : return ('<BS>');      ! 08
!
        ['	'] : return ('<HT>'); ! 09
        ['
'] : return ('<LF>');      ! 10
        [''] : return ('<VT>');      ! 11
        [''] : return ('<FF>');      ! 12
        [''] : return ('<CR>');      ! 13
!
        [''] : return ('<SO>');      ! 14
        [''] : return ('<SI>');      ! 15
        [''] : return ('<DLE>');     ! 16
        [''] : return ('<DC1>');     ! 17
        [''] : return ('<DC2>');     ! 18
        [''] : return ('<DC3>');     ! 19
        [''] : return ('<DC4>');     ! 20
        [''] : return ('<NAK>');     ! 21
        [''] : return ('<SYN>');     ! 22
        [''] : return ('<ETB>');     ! 23
        [''] : return ('<CAN>');     ! 24
        [''] : return ('<EM>');      ! 25
        [''] : return ('<SUB>');     ! 26
        [''] : return ('<ESC>');     ! 27
        [''] : return ('<FS>');      ! 28
        [''] : return ('<GS>');      ! 29
        [''] : return ('<RS>');      ! 30
        [''] : return ('<US>');      ! 31
        [INRANGE, OUTRANGE] : return (char);
    endcase;

endprocedure;

!*----------------------------------------------------------------------------*!

! This procedure returns a printable string for a non-printable DEC
! Multinational character.

procedure ep$xlate_multinationals (char)

    ! The backwards questions mark is the placeholder for many DEC
    ! Multinational characters in the range from ASCII(127) thru
    ! ASCII(255) on the VT2xx series of terminals.

    ! The checkerboard mark is the placeholder for all DEC Multinational
    ! characters in the range from ASCII(127) thru ASCII(255) on the
    ! VT1xx series of terminals.

    CASE char FROM '' TO ''

        [''] : return ('<DEL>');   ! 127
        [''] : return ('<x80>');   ! 128
        [''] : return ('<x81>');   ! 129
        [''] : return ('<x82>');   ! 130
        [''] : return ('<x83>');   ! 131
        [''] : return ('<IND>');   ! 132
        [''] : return ('<NEL>');   ! 133
        [''] : return ('<SSA>');   ! 134
        [''] : return ('<ESA>');   ! 135
        [''] : return ('<HTS>');   ! 136
        [''] : return ('<HTJ>');   ! 137
        [''] : return ('<VTS>');   ! 138
        [''] : return ('<PLD>');   ! 139
        [''] : return ('<PLU>');   ! 140
        [''] : return ('<RI>');    ! 141
        [''] : return ('<SS2>');   ! 142
        [''] : return ('<SS3>');   ! 143
        [''] : return ('<DCS>');   ! 144
        [''] : return ('<PU1>');   ! 145
        [''] : return ('<PU2>');   ! 146
        [''] : return ('<STS>');   ! 147
        [''] : return ('<CCH>');   ! 148
        [''] : return ('<MW>');    ! 149
        [''] : return ('<SPA>');   ! 150
        [''] : return ('<EPA>');   ! 151
        [''] : return ('<x98>');   ! 152
        [''] : return ('<x99>');   ! 153
        [''] : return ('<x9A>');   ! 154
        [''] : return ('<CSI>');   ! 155
        [''] : return ('<ST>');    ! 156
        [''] : return ('<OSC>');   ! 157
        [''] : return ('<PM>');    ! 158
        [''] : return ('<APC>');   ! 159
        [''] : return ('<xA0>');   ! 160
        [''] : return ('<!!>');    ! 161
        [''] : return ('<C/>');    ! 162
        [''] : return ('<L->');    ! 163
        [''] : return ('<xA4>');   ! 164
        [''] : return ('<Y->');    ! 165
        [''] : return ('<xA6>');   ! 166
        [''] : return ('<S0>');    ! 167
        [''] : return ('<X0>');    ! 168
        [''] : return ('<C0>');    ! 169
        [''] : return ('<a_>');    ! 170
        [''] : return ('<<<>');    ! 171
        [''] : return ('<xAC>');   ! 172
        [''] : return ('<xAD>');   ! 173
        [''] : return ('<xAE>');   ! 174
        [''] : return ('<xAF>');   ! 175
        [''] : return ('<0^>');    ! 176
        [''] : return ('<+->');    ! 177
        [''] : return ('<2^>');    ! 178
        [''] : return ('<3^>');    ! 179
        [''] : return ('<xB4>');   ! 180
        [''] : return ('</U>');    ! 181
        [''] : return ('<P!>');    ! 182
        [''] : return ('<.^>');    ! 183
        [''] : return ('<xB8>');   ! 184
        [''] : return ('<1^>');    ! 185
        [''] : return ('<o_>');    ! 186
        [''] : return ('<>>>');    ! 187
        [''] : return ('<1/4>');   ! 188
        [''] : return ('<1/2>');   ! 189
        [''] : return ('<xBE>');   ! 190
        [''] : return ('<??>');    ! 191
        [''] : return ('<A`>');    ! 192
        [''] : return ("<A'>");    ! 193
        [''] : return ('<A^>');    ! 194
        [''] : return ('<A~>');    ! 195
        [''] : return ('<A">');    ! 196
        [''] : return ('<A*>');    ! 197
        [''] : return ('<AE>');    ! 198
        [''] : return ('<C,>');    ! 199
        [''] : return ('<E`>');    ! 200
        [''] : return ("<E'>");    ! 201
        [''] : return ('<E^>');    ! 202
        [''] : return ('<E">');    ! 203
        [''] : return ('<I`>');    ! 204
        [''] : return ("<I'>");    ! 205
        [''] : return ('<I^>');    ! 206
        [''] : return ('<I">');    ! 207
        [''] : return ('<xD0>');   ! 208
        [''] : return ('<N~>');    ! 209
        [''] : return ('<O`>');    ! 210
        [''] : return ("<O'>");    ! 211
        [''] : return ('<O^>');    ! 212
        [''] : return ('<O~>');    ! 213
        [''] : return ('<O">');    ! 214
        [''] : return ('<OE>');    ! 215
        [''] : return ('<O/>');    ! 216
        [''] : return ('<U`>');    ! 217
        [''] : return ("<U'>");    ! 218
        [''] : return ('<U^>');    ! 219
        [''] : return ('<U">');    ! 220
        [''] : return ('<Y">');    ! 221
        [''] : return ('<xDE>');   ! 222
        [''] : return ('<ss>');    ! 223
        [''] : return ('<a`>');    ! 224
        [''] : return ("<a'>");    ! 225
        [''] : return ('<a^>');    ! 226
        [''] : return ('<a~>');    ! 227
        [''] : return ('<a">');    ! 228
        [''] : return ('<a*>');    ! 229
        [''] : return ('<ae>');    ! 230
        [''] : return ('<c,>');    ! 231
        [''] : return ('<e`>');    ! 232
        [''] : return ("<e'>");    ! 233
        [''] : return ('<e^>');    ! 234
        [''] : return ('<e">');    ! 235
        [''] : return ('<i`>');    ! 236
        [''] : return ("<i'>");    ! 237
        [''] : return ('<i^>');    ! 238
        [''] : return ('<i">');    ! 239
        [''] : return ('<xF0>');   ! 240
        [''] : return ('<n~>');    ! 241
        [''] : return ('<o`>');    ! 242
        [''] : return ("<o'>");    ! 243
        [''] : return ('<o^>');    ! 244
        [''] : return ('<o~>');    ! 245
        [''] : return ('<o">');    ! 246
        [''] : return ('<oe>');    ! 247
        [''] : return ('<o/>');    ! 248
        [''] : return ('<u`>');    ! 249
        [''] : return ("<u'>");    ! 250
        [''] : return ('<u^>');    ! 251
        [''] : return ('<u">');    ! 252
        [''] : return ('<y">');    ! 253
        [''] : return ('<xFE>');   ! 254
        [''] : return ('<xFF>');   ! 255
        [INRANGE, OUTRANGE] : return (char);
    endcase;

endprocedure;

