procedure send_ch(ch:char);
var was_sent : char;
    count : integer;
begin
  case mode of
    CW : if (ch = #13) then ch := #32;
    RTTY,ASCII : ;
  end;
  ch := UpCase(ch);
  send_interrupt := FALSE;
  kam_out(ch);
  repeat
    repeat
      delay(10);
      chk_kbd;
    until (send_interrupt = TRUE) OR
          (char_ready = TRUE)     OR
          (state = receive);
    if (char_ready = TRUE)
    then was_sent := kam_in
    else begin
           was_sent := ch;
           clear_buffer;
         end;
  until was_sent = ch;
  if pause_flag then
  begin
    wait_for_key;
    pause_flag := false;
  end;
end;

procedure send_char(ch: char);
begin
  attr_pos := 80*(yout - 1) + xout - 1;
  if (attr_pos > lead_attr ) then
    case vid_type of
      0 : mono_screen[attr_pos].a := xmt_attrib;
      1 : color_screen[attr_pos].a := xmt_attrib;
    end;
  xout := xout + 1;
  if xout > scrn_width then
  begin
    xout := 1;
    yout := yout + 1;
  end;
  attr_pos := 80*(yout - 1) + xout - 1;
  if (yout in [out_start_line .. out_end_line]) then
    case vid_type of
      0 : mono_screen[attr_pos].a := status_attrib;
      1 : color_screen[attr_pos].a := status_attrib;
    end;
  if (ch <> #13)
    then send_ch(ch)
    else if (last_char_sent <> #13)
           then send_ch(ch);
  if ch = #13 then
  begin
    attr_pos := 80*(yout - 1) + xout - 1;
    if (attr_pos > lead_attr ) then
    case vid_type of
      0 : mono_screen[attr_pos].a := xmt_attrib;
      1 : color_screen[attr_pos].a := xmt_attrib;
    end;
    yout := yout + 1;
    xout := 0;
  end;
  last_char_sent := ch;
end;

procedure send_file;
label file_done,
      send_read_error;
var filename : file_type;
    filespec : file;
    recsread : integer;
    filebuff : array[0..2047] of byte;
    chr_pntr,nbr_chr : integer;
    file_chr : char;

  procedure more_data;
  var i : integer;
  begin
    blockread(filespec,filebuff,16,recsread);
    if (recsread = 0) OR (IOresult <> 0)  then stop_flag := TRUE;
    nbr_chr := 128*recsread-1;
    chr_pntr := 0;
  end;

  procedure next_char;
  begin
    chr_pntr := chr_pntr + 1;
    if (chr_pntr > nbr_chr) then more_data;
    chk_kbd;
  end;

begin
  file_mode := TRUE;
  prompt_color;
  get_file_name(filename,
                20,aux_line,'Text',1,1,80,24,3);
  gotoxy(20,aux_line); aux_color; ClrEol;
  write('FILE XMT MODE : ',filename);
  if filename <> '' then
  begin
    assign(filespec,filename);
    {$I-} reset(filespec);
    if (IOresult <> 0) then goto send_read_error;
    clear_transmit_screen;
    state := transmit;
    if (xmt_ON = FALSE) then xmt_mode;
    stop_flag := FALSE;
    repeat
      more_data;
      if (state = receive) then goto file_done;
      repeat
        file_chr := chr(filebuff[chr_pntr]);
        if (state = receive) OR (file_chr = ^Z) then goto file_done;
        if (file_chr in [#07,#13,' '..'z']) then
        begin
          add_char(file_chr);
          send_char(file_chr);
        end;
        chr_pntr := chr_pntr + 1;
        if (state = receive) then goto file_done;
      until chr_pntr > nbr_chr;
    until  state = receive;
file_done:
    close(filespec);
  end;
send_read_error:
    {$I+}
    file_mode := FALSE;
    out_ptr := inp_ptr;
    clean_up_display;
    gotoxy(20,aux_line); aux_color; ClrEol;
    sho_status;
end;

procedure halt_xmt;
begin
  stop_flag := TRUE;
  clean_up_display;
  if (attr_pos > lead_attr ) then
    case vid_type of
      0 : mono_screen[attr_pos].a := xmt_attrib;
      1 : color_screen[attr_pos].a := xmt_attrib;
    end;
  inp_ptr := out_ptr;
  xout := xkbd - 1;
  yout := ykbd;
  clear_buffer;
  rcv_mode;
  state := receive;
  sho_status;
end;

procedure xmtg;
begin
  if (xmt_ON = FALSE) then
  begin
    xmt_mode;
    sho_status;
  end;
  if (inp_ptr = out_ptr) AND (auto_switch = TRUE) then
    begin
      case mode of
        CW  :  xmt_time_out := cw_off_delay;
        ASCII,
        RTTY : xmt_time_out := xmt_off_delay;
      end;
      while (   (xmt_time_out > 0)
            AND (out_ptr = inp_ptr)
            AND (send_INTERRUPT = FALSE) ) do
        begin
          delay(100);
          xmt_time_out := xmt_time_out - 1;
          chk_kbd;
        end;
      if (out_ptr = inp_ptr) then
      begin
        halt_xmt;
        exit;
      end;
    end;
  if (out_ptr <> inp_ptr) then
  begin
    out_ptr := (out_ptr + 1) AND buf_size;
    send_char(kbd_buffer[out_ptr]);
  end;
end;

