{-------------------------------------------------------------}
{                papovox - interacao via teclado
{-------------------------------------------------------------}

unit ppcontro;

interface
uses dvwin, dvcrt, winsock, dvinet, mmsystem,
     windos, winprocs, wintypes, dvgrav, strings,
     ppvars, ppmsg, ppsom, pprede, pparq, ppurgent, ppsnomes, videovox;

procedure batePapo;

implementation
var
    horaConec, minConec: word;
    ultMsgParceiro, ultMsgMinha: string;

{--------------------------------------------------------}
{              altera parâmetros de fala
{--------------------------------------------------------}

procedure alteraFala;
var c, c2: char;
begin
     mensagem ('PPQVELOC', 0);   {'Qual a velocidade de fala, de 1 a 4 ? '}
     sintLeTecla (c, c2);
     writeln;
     if c in ['1'..'4'] then
         begin
             sintFim;
             sintInic (ord(c) - ord('0'), sintAmbiente ('PAPOVOX', 'DIRPAPOVOX'));
         end;

     mensagem ('PPSOLET', 0);    {'Soletra digitação ? '}
     sintLeTecla (c, c2);
     writeln;
     soletrando := upcase(c) <> 'N';
end;

{--------------------------------------------------------}
{               informa tempo de conexão
{--------------------------------------------------------}

procedure informaTempos;
var
    hora, min, seg, cent: word;
begin
    mensagem ('PPHORA', 0);     {'A hora atual é '}
    gettime (hora, min, seg, cent);
    sintWriteInt (hora);
    mensagem ('PPXHORAS', 0);   {horas}
    if min <> 0 then
        begin
            sintWriteInt (min);
            mensagem ('PPXMINUT', 1);   {minutos}
        end;

    mensagem ('PPHCONE', 0);     {'Hora da conexão com o parceiro:'}

    sintWriteInt (horaConec);
    mensagem ('PPXHORAS', 0);   {horas}
    if min <> 0 then
        begin
            sintWriteInt (minConec);
            mensagem ('PPXMINUT', 1);   {minutos}
        end;
end;

{--------------------------------------------------------}
{              ajuda comandos de teclado
{--------------------------------------------------------}

procedure ajudaTeclado;
begin
    mensagem ('PPAJUT0', 1);     {'Os comandos são os seguintes'}
    mensagem ('PPAJUT1', 1);     {'F1 ajuda, control F1 repete mensagem'}
    mensagem ('PPAJUT2', 1);     {'F2 transmite um arquivo'}
    mensagem ('PPAJUT4', 1);     {'F4 altera fala'}
    mensagem ('PPAJUT5', 1);     {'F5 mensagem urgente'}
    mensagem ('PPAJUT6', 1);     {'F6 informa ip desta conexão'}
    mensagem ('PPAJUT7', 1);     {'F7 repete fala, control F7 repete msg urgente'}
    mensagem ('PPAJUT8', 1);     {'F8 informa tempo de conexão'}
    mensagem ('PPAJUT9', 1);     {'F9 aciona leitor de telas'}
end;

{--------------------------------------------------------}
{                 executa fala pendente
{--------------------------------------------------------}

procedure falaDaFila;
begin
    if ffilaFala <> rfilaFala then
        begin
            gotoxy (1, wherey);
            clreol;
            textColor (WHITE);
            ultMsgParceiro := filaFala [ffilaFala];
            ffilaFala := (ffilaFala + 1) mod maxFilaFala;
            sintWriteln (ultMsgParceiro);
            delay (500);
            textColor (LIGHTGRAY);
        end;
end;

{--------------------------------------------------------}
{               processa dados da rede
{--------------------------------------------------------}

function procDadosRede: boolean;
var bufinho: array [0..2] of byte;
    bufao:   array [0..512] of char;
    lidos, aler, lidosAgora: integer;
begin
    procDadosRede := false;

    lidosAgora := recv (sock, @bufinho[0], 3, 0);

    if lidosAgora < 1 then
        exit;

    aler := bufinho [1] or (bufinho [2] shl 8);

    lidos := 0;
    while aler > 0 do
        begin
            if aler > 512 then
                lidosAgora := recv (sock, @bufao[lidos], 512, 0)
            else
                lidosAgora := recv (sock, @bufao[lidos], aLer, 0);
            if lidosAgora <= 0 then
                exit;

            lidos := lidos + lidosAgora;
            aler := aler - lidosAgora;
        end;
    bufao [lidos] := #$0;
    procDadosRede := true;

    case bufinho[0] of
        DADOTECLADO:   begin
                           bipSpeaker (47);
                           filaFala [rfilaFala] := strPas (bufao);
                           rfilaFala := (rfilaFala + 1) mod MAXFILAFALA;
                       end;

        INICIOSOM:     trataInicioSom;
        DADOSOM:       trataRecebeSom (bufao, lidos);
        FIMSOM:        trataFimSom;

        INICIOARQENVIA:   trataInicioRecebe (bufao);
        FIMARQENVIA:      begin
                              trataFimRecebe;
                              if wherex <> 1 then writeln;
                          end;
        DADOENVIA:        trataArqRecebe (bufao, lidos);
        CANCARQENVIA:     begin
                              trataCancArqRecebe;
                              if wherex <> 1 then writeln;
                          end;

        PODEMANDAR:       trataInicioTransm;
        CANCELAMANDAR:    trataCancTransm;
    end;
end;

{--------------------------------------------------------}
{           processa teclas comuns
{--------------------------------------------------------}

procedure processaTeclasComuns (c: char);

    procedure escreveBufTec;
    begin
        if length (bufTec) < 80 then
            begin
                gotoxy (1, wherey);
                write (buftec);
            end
        else
            begin
                gotoxy (1, wherey);
                write (copy (buftec, length(buftec)-78, 79));
            end;
        clreol;
    end;


begin
    if c = ESC then
        conversando := false
    else
    if c = ENTER then
        begin
            sintClek;
            ultMsgMinha := bufTec;
            if not enviaRede (DADOTECLADO, @bufTec[1], length (bufTec)) then
                 conversando := false;

            gotoxy (1, wherey);
            writeln (copy (bufTec, 1, 79));
            bufTec := '';
        end

    else
    if c = ^Y then
       begin
           gotoxy (1, wherey);
           clreol;
           sintSom ('_CPOAPA');
           bufTec := '';
       end

    else
    if c = BS then
        begin
            if bufTec <> '' then
                begin
                     sintSom ('_DEL');
                     sintCarac (bufTec [length(bufTec)]);
                     delete (bufTec, length(bufTec), 1);
                end;
            escreveBufTec;
        end
    else
        begin
            if length (bufTec) > maxtec-1 then
                sintBip
            else
                begin
                    bufTec := bufTec + c;
                    if soletrando then
                        sintCarac (c);
                    escreveBuftec;
                end;
        end
end;

{--------------------------------------------------------}
{            tratamento das teclas de função
{--------------------------------------------------------}

procedure processaFuncoesDeTeclado (c: char);
var
    xc, yc: integer;
begin
    if (c in [F2, F3, F5]) and (wherex <> 1) then
        processaTeclasComuns (ENTER);

    case c of
        F1:  ajudaTeclado;
     CTLF1:  if buftec = '' then
                 sintetiza (ultMsgMinha)
             else
                 sintetiza (buftec);
        F2:  transmiteArq;
        F3:  cancelaRecepcao;
        F4:  alteraFala;
        F5:  enviaMsgUrgente;
        F6:  informaIp;
        F7:  sintetiza (ultMsgParceiro);
     CTLF7:  sintetiza (ultMsgUrgente);
        F8:  informaTempos;
        F9:  begin
                 sintBip; sintBip;
                 xc := wherex;
                 yc := wherey;
                 window (1, 1, 80, 25);
                 gotoxy (xc, yc);
                 leitorDeTela;
                 window (1, 1, 80, 24);
                 gotoxy (xc, yc);
             end;

    else
        mensagem ('PPAPTF1', 1);   {Aperte F1 para ajuda}
    end;
end;

{--------------------------------------------------------}
{                  realiza o bate papo
{--------------------------------------------------------}

procedure batePapo;
var
    inibate, fimbate: string;
    c: char;
    i: integer;
    s: string;
    lidosSom, lidosDisco: integer;
    seg, centSeg: word;

label comunicCaiu, fecha;

begin
    while keypressed do readkey;

    gettime (horaConec, minConec, seg, centSeg);

    window (1,1,80,25);
    clrScr;

    inibate := sintAmbiente ('PAPOVOX', 'SOMINIBATE');
    sintsom (inibate);
    logonUsuario (enderUsuario, 'talking');

    mensagem ('PPINIPAP', 1);  {Iniciando bate papo}

    textBackground (BLUE);
    gotoxy (1, 25);
    mensagem ('PPESCTRM', 0);   {Tecle ESC para desligar, F1 para ajuda}
    textBackground (BLACK);

    window (1,1,80,24);
    gotoxy (1, 4);

    bufTec := '';
    enviandoSom := false;
    enviouTodoSom := true;

    ffilaFala := 0;
    rfilaFala := 0;

    autorEnvioPendente := false;
    enviandoArq := false;
    recebendoArq := false;

    ultMsgParceiro := '';
    ultMsgMinha := '';

    c := #0;
    conversando := true;
    while conversando do
        begin
            {--- processamento do teclado ---}

            while keypressed do
                begin
                   c := readkey;
                   if c <> #$0 then
                       processaTeclasComuns (c)
                   else
                       begin
                           c := readkey;
                           processaFuncoesDeTeclado (c);
                       end;
                end;

            if wherex = 1 then
                falaDaFila;

            {--- processamento de mensagem urgente ---}

            if temMsgUrgente then
                begin
                    if wherex <> 1 then writeln;
                    recebeMsgUrgente;
                end;

            {--- processamento da chegada de rede ---}

            if chegouRede (sock) then
                 if not procDadosRede then
                     conversando := false;

            {--- processamento da bufferizacao do som ---}

            if (((getkeystate (vk_shift)   shr 15) and 1) <> 0) and
               (((getkeystate (vk_control) shr 15) and 1) <> 0)  then
                begin
                    if (not enviandoSom) and enviouTodoSom then
                        inicioEnvioSom;
                    monitoraBuffersSom;
                end
            else
                begin
                   if enviandoSom then
                       begin
                           terminaGravacao;
                           reset (arqGravador, 1);   { para poder continuar lendo }
                           enviandoSom := false;
                       end;
                end;

            if (not enviandoSom) and (not enviouTodoSom) then
                if tamSomEnviado < tamGravado then
                    monitoraBuffersSom
                else
                    terminaEnvioSom;

            {--- processamento do envio do arquivo ---}

            if enviandoArq and (not autorEnvioPendente) then
                begin
                    if eof (arqEnvia) then
                        begin
                            close (arqEnvia);
                            if not enviaRede (FIMARQENVIA, NIL, 0) then
                                 goto comunicCaiu;
                            mensagem ('PPBEMTRA', 1);   {Arquivo bem transmitido}
                            enviandoArq := false;
                            autorEnvioPendente := false;
                        end
                    else
                        begin
                            {$I-}  blockRead (arqEnvia, bufEnvia, 512, lidosDisco);   {$I+}
                            if ioresult <> 0 then
                                begin
                                    mensagem ('PPPROTRA', 1);   {Problemas na transmissão do arquivo}
                                    if not enviaRede (CANCELAMANDAR, NIL, 0) then
                                         goto comunicCaiu;
                                end
                            else
                            if not enviaRede (DADOENVIA, @bufEnvia, lidosDisco) then
                                 goto comunicCaiu;

                            contaSpeaker := contaSpeaker + 1;
                            if contaSpeaker > 8 then
                                begin
                                    bipSpeaker (44);
                                    contaSpeaker := 0;
                                end;
                        end;
                end;
        end;

fecha:
    window (1, 1, 80, 25);
    gotoxy (1, 25);
    clreol;
    writeln;

    fechaConexao (sock);
    fimbate:= sintAmbiente ('PAPOVOX', 'SOMFIMBATE');
    sintsom (fimbate);
    mensagem ('PPFIMPAP', 1);  {Fim do bate papo}

    logonUsuario (enderUsuario, 'endtalk');
    exit;

comunicCaiu:
    mensagem ('PPERRCOM', 1);   {Erro de comunicação na Internet}
    goto fecha;
end;

end.
