{-------------------------------------------------------------}
{
{           cartaVox - manipulador de cópias carbono
{
{-------------------------------------------------------------}

unit carCC;

interface

uses
    dvcrt,
    dvWin,
    dvForm,
    dvHora,
    shellApi,
    sysutils,
    windows,
    carRede,
    winSock,   //Declarar depois de carRede
    carApeli,
    carMsg,
    carTela,
    carUtil,
    carDecod,
    carVars;

procedure limpaListaCarbono (var pt: pListaCC);
procedure geraListaCarbono (nomeDest: string; bcc: boolean);
procedure geraRCPTCC;

procedure gravaCC;
procedure carregaListaCarbono (lista: string; var pt: plistaCC);
procedure extraiCC (nCar: integer);
procedure folheiaCopiasCarbono (var pt: pListaCC);
function  respondeTodosCC (nCar: integer): boolean;
procedure listarCopiasCarbono (nCar: integer);

implementation

var
    nomeDestinatario: string;

{-------------------------------------------------------------}
{       gera lista de cópias carbono
{-------------------------------------------------------------}

procedure limpaListaCarbono (var pt: pListaCC);
var prox: pListaCC;
begin
    while pt <> NIL do
        begin
            prox := pt^.prox;
            dispose (pt);
            pt := prox;
        end;
    pt := NIL;
end;

{-------------------------------------------------------------}
{       inverte a ordem de uma lista
{-------------------------------------------------------------}

procedure inverteListaCC (var pl: pListaCC);
var p, aux: pListaCC;
begin
    p := NIL;
    while pl <> NIL do
        begin
            aux := pl;
            pl := pl^.prox;

            aux^.prox := p;
            p := aux;
        end;
    pl := p;
end;

{-------------------------------------------------------------}
{       le a lista de arquivos CC ou BCC
{-------------------------------------------------------------}

procedure leListaCC (var pl: pListaCC);
var
    endereco, aux: string;
    c, c2: char;
    i, cont, numCartas: integer;
    mudo, soUmEndereco: boolean;
    pCarb: pListaCC;

label deNovo, fim;

    procedure jogaNaListaCC;
    var p: pListaCC;
    begin
        if (endereco = nomeDestinatario) or
           (pos (endereco, nomeDestinatario) <> 0) or
           (pos (nomeDestinatario, endereco) <> 0)  then
                exit;
        if pCC <> NIL then
            begin
                p := pCC;
                while p <> NIL do
                    begin
                        if (endereco = p^.nome) or
                           (pos(endereco, p^.nome)<>0) or
                           (pos(p^.nome, endereco) <> 0) then
                                exit;
                        p := p^.prox;
                    end;
            end;

        if pbCC <> NIL then
            begin
                p := pbCC;
                while p <> NIL do
                    begin
                        if (endereco = p^.nome) or
                           (pos(endereco, p^.nome)<>0) or
                           (pos(p^.nome, endereco) <> 0) then
                                exit;
                        p := p^.prox;
                    end;
            end;

        numCartas := numCartas + 1;
        new (pCarb);
        with pCarb^ do
            begin
                nome := endereco;
                prox := pl;
                pl := pCarb;
            end;
    end;


begin
    numCartas := 0;
    soUmEndereco := true;
    repeat
deNovo:
        sintBip;
        endereco := '';
        c := sintEditaCampo (endereco, 1, wherey, 255, 80, true);
        writeln;
        if (c = BAIX) or (c = CIMA) then
            begin
                endereco := folhearApelidos (endereco);
                soUmEndereco := not temMaisDeUmEndeereco (endereco);
            end
        else
        if endereco = '*' then
            soUmEndereco := false;

        if trim (endereco) = '' then
            goto fim
        else
        if soUmEndereco then
            begin
                if endereco[1] = '*' then
                    begin
                        delete (endereco, 1, 1);
                        endereco := buscaApelido (endereco);
                        if endereco = '' then
                            begin
                                msgBaixo ('CTAPEINV');   {'Apelido inválido'}
                                goto deNovo;
                            end;
                        repeat
                            mensagem ('CTENVPAR', 0);   {'Enviando para: '}
                            sintWriteln (endereco);
                            mensagem ('CTCNFDST', 0);  {'Confirma destino {s/n) ? '}
                            c := upcase(popupMenuPorLetra ('SN'));
                            writeln;
                            case c of
                                ESC: goto fim;
                                'N': goto deNovo;
                            end;
                        until c in ['N', 'S', ENTER, ESC];
                    end;
                if pos ('@', endereco) <> 0 then
                    jogaNaListaCC
                else
                    mensagem ('CTAPEINV', 2); {'Apelido inválido'}
            end
        else
            begin
                msgBaixo ('CTLIGERA'); {'Gerando cartas'}
                aux := trim (endereco);
                if aux = '*' then
                    soUmEndereco := true; //Todos do caderno de apelidos
                mudo := false;
                i := 1;
                cont := 0;
                repeat
                    if not soUmEndereco then
                        begin
                            if aux = '' then
                                endereco := ''
                            else
                                begin
                                    endereco := copy (aux, 1, pos('>', aux));
                                    delete (aux, 1, pos('>', aux));
                                    if endereco[1] = ',' then
                                        delete (endereco, 1, 1);
                                end;
                        end
                    else
                        endereco := pegaEMailApelidos (i); //Pega do caderno de apelidos

                    if keypressed then
                        begin
                            c2 := readkey;
                            if c2 = ESC then
                                endereco := ''
                            else
                                mudo := not mudo;
                        end;

                    if pos ('@', endereco) <> 0 then
                        begin
                            if not mudo then
                                begin
                                    repeat
                                        mensagem ('CTENVPAR', 0);   {'Enviando para: '}
                                        sintWriteln (endereco);
                                        mensagem ('CTCNFDST', 0);  {'Confirma destino {s/n) ? '}
                                        mensagem ('CTOUTPT', 0);  {' Ou tecle T para todos '}
                                        c := upcase(popupMenuPorLetra ('SNT'));
                                        writeln;
                                    until c in ['S', 'N', 'T', ENTER, ' ', ESC];
                                    case c of
                                        ESC: goto fim;
                                        'T', ' ': begin
                                                        mudo := not mudo;
                                                        jogaNaListaCC;
                                                  end;
                                        'N':; //Não joga na lista
                                    else
                                        jogaNaListaCC;
                                    end;
                                end
                            else
                                begin
                                    jogaNaListaCC;
                                    if (cont mod 50) = 0 then
                                        begin
                                            sintBip;
                                            cont := 0;
                                        end;
                                    cont := cont + 1
                                end;
                        end;
                    i := i + 1;
                until endereco = '';
            end;
    until endereco = '';

fim:
    if numCartas = 0 then exit;
    delay (250);
    sintWriteint (numCartas);
    write (' ');
    if numCartas > 1 then
        mensagem ('CTCARTAS', 0) {'Cartas'}
    else
        mensagem ('CTCARTA', 0); {'Carta'}
    write (' ');
    mensagem ('CTCARBON', 1); {'carbono'}
end;

{-------------------------------------------------------------}
{       gera lista de cópias carbono
{-------------------------------------------------------------}

procedure geraListaCarbono (nomeDest: string; bcc: boolean);

begin
    {cuidado, esta rotina adiciona dados as listas CC ou BCC atuais, nao as limpa !}

    nomeDestinatario := nomeDest;
    if bcc then
        mensagem ('CTDIGBCC', 1)   {'Digite os endereços eletrônicos para os carbonos ocultos'}
    else
        mensagem ('CTDIGCC', 1);   {'Digite os endereços eletrônicos para os carbonos'}
    mensagem ('CTENTCC', 1);   {'Tecle ENTER após cada nome e após o último tecle mais um ENTER'}

    if bcc then
        begin
            leListaCC (pBCC);
            inverteListaCC (pBCC);
        end
    else
        begin
            leListaCC (pCC);
            inverteListaCC (pCC);
        end;
end;

{-------------------------------------------------------------}
{       grava cabeçalho das CC e BCC no arquivo a enviar
{-------------------------------------------------------------}

procedure geraRCPTCC;

    {-------------------------------------------------------------}

    procedure grava (p: pListaCC);
    var s: string;
        i1, i2: integer;
    begin
        while p <> NIL do
            begin
                i1 := pos ('<', p^.nome);
                if i1 <> 0 then
                    begin
                        i2 := pos ('>', p^.nome);
                        if i2 = 0 then i2 := length (p^.nome);
                        s := copy (p^.nome, i1, i2-i1+1);
                        writeln (arqEnv, 'RCPT TO:', s)
                    end
                else
                    writeln (arqEnv, 'RCPT TO:<', p^.nome, '>');

                p := p^.prox;
            end;
    end;

    {-------------------------------------------------------------}

begin
    grava (pCC);
    grava (pBCC);
end;

{-------------------------------------------------------------}
{       grava CC no arquivo a enviar
{-------------------------------------------------------------}

procedure gravaCC;
var p: pListaCC;
begin
    if pCC <> NIL then
        begin
            write (arqEnv, 'Cc: ');
            p := pCC;
            while p <> NIL do
                begin
                    write (arqEnv, p^.nome);
                    p := p^.prox;
                    if p <> NIL then
                        begin
                            writeln (arqEnv, ',');
                            write (arqEnv, '    ');
                        end
                    else
                        writeln (arqEnv);
                end;
        end;
end;

{-------------------------------------------------------------}
{       Carrega os e-mails da string na lista cc ou bcc
{-------------------------------------------------------------}

procedure carregaListaCarbono (lista: string; var pt: plistaCC);
var
    i: integer;
    ptAux: plistaCC;
begin
    lista := trim (lista);
    if lista = '' then
        exit;

    repeat
        i := pos (',', lista);
        if i = 0 then i := length (lista) + 1;

//Teste para não inserir o remetente na lista carbono
        if pos(enderUsuario, copy (lista, 1, i-1)) = 0 then
            begin
                new (ptAux);
                ptAux^.nome := trim(copy (lista, 1, i-1));
                ptAux^.prox := pt;
                pt := ptAux;
            end;

        delete (lista, 1, i);
        lista := trim (lista);
    until lista = '';
end;

{-------------------------------------------------------------}
{       extrai uma lista de CC de uma carta, procura no "To:" também
{-------------------------------------------------------------}

procedure extraiCC (nCar: integer);
var s: string;
begin
    s := '';
    if regLido [nCar]^.carta^.cc <> '' then
        s := regLido [nCar]^.carta^.cc;
    if (temMaisDeUmEndeereco (regLido [nCar]^.carta^.to_)) or
      ((pos('@', regLido[nCar]^.carta^.to_) <> 0) and
      (pos(enderUsuario, regLido[nCar]^.carta^.to_) = 0) and
      (pos(regLido[nCar]^.carta^.reply_to, regLido[nCar]^.carta^.to_) = 0) and
      (regLido [nCar]^.carta^.reply_to <> regLido [nCar]^.carta^.from)) then 
        if s <> '' then
            s := s +','+ regLido [nCar]^.carta^.to_
        else
            s := regLido [nCar]^.carta^.to_;

            decodificarString (s);
    if trim (s) <> '' then
        carregaListaCarbono (s, pCC);
end;

{-------------------------------------------------------------}
{       Ajuda das opções do folheamento de carbonos
{-------------------------------------------------------------}

procedure ajudaFolheCarbono;
begin
    telaFolheiaCarbono (folheiaNumItens);
    textBackground (BLUE);
    mensagem ('CTAJUD01', 0); {'As opções são:'}
    textBackground (BLACK);
    writeln;
    mensagem ('CTAJFC01', 1); {'CTRL+A - Apagar'}
    mensagem ('CTAJFC02', 1); {'CTRL+Q - Informa quantas do total'}
    mensagem ('CTAJFC03', 1); {'CTRL+S - Informa quantas selecionadas do total'}
    mensagem ('CTAJFL10', 1); {'F5 - Procurar'}
    mensagem ('CTAJFP11', 1); {'BARRA DE ESPAÇO - Seleciona ou tira seleção'}
    mensagem ('CTAJFP12', 1); {'* - Seleciona tudo'}
    mensagem ('CTAJFP13', 1); {'/ - Tira seleção de tudo'}
    mensagem ('CTAJFL07', 1); {'ESC - Terminar folheamento'}

    if keypressed and (readkey <> ESC) then
        begin
            limpaBufTec;
            readkey;
        end;
    limpaBufTec;
end;


{--------------------------------------------------------}
{       procura próximo item no folheamento
{--------------------------------------------------------}

var nomeBusc: string; //Usado na procura do folheamento

function procuraProximoItem(numFolhe: integer): integer;
var
    i: integer;
    buscado, item: string;
    selecionado: boolean;
begin
    buscado := semAcentos (nomeBusc);
     for i := numFolhe +1 to folheiaNumItens do
        begin
            folheiaObtemItem (i, item, selecionado);
            if pos (buscado, semAcentos (item)) <> 0 then
                begin
                    procuraProximoItem := i;
                    exit;
                end;
        end;
    sintbip;
    procuraProximoItem := numFolhe;
end;

{-------------------------------------------------------------}
{       Procura um item no folheamento, usa a fuction procuraProximoItem
{-------------------------------------------------------------}

function procuraItem (numFolhe: integer): integer;
begin
    procuraItem := numFolhe;
    gotoxy (1, 24); clreol;
    textbackground (red);
    mensagem ('CTPALPRO', 0);{'Digite a palavra a procurar: '}
    textbackground (black);
    sintReadln (nomeBusc);
    if nomeBusc = '' then
        mensagem ('CTDESIST', 1) {'Desistiu ...'}
    else
        procuraItem := procuraProximoItem (numFolhe);
end;

{-------------------------------------------------------------}
{       Folheamento da lista de copias carbono
{-------------------------------------------------------------}

procedure folheiaCopiasCarbono (var pt: pListaCC);
var
    c, c2: char;
    numCarbonos, numFolhe, i: integer;
    item: string;
    podeFalar, selecionado: boolean;
    pCarb: pListaCC;

    procedure inicializaFolheamentoCarbonos;
    begin
        numCarbonos := 0;
        folheiaCria (1, 8, 80, 21);
        while pt <> NIL do
            begin
                numCarbonos := numCarbonos + 1;
                item := pt^.nome;
                deletaAspas (item);
                deletaMenorMaior (item);
                folheiaAdicionaEspecial (pt^.nome, false, item);
                pt := pt^.prox;
            end;
    end;


label fim;
begin
        telaFolheiaCarbono (0);
    inicializaFolheamentoCarbonos;
    if folheiaNumItens <= 0 then
        begin
            msgBaixo ('CTLICAVA'); {'Lista de copias carbono vazia.'}
            goto fim;
        end;
    numFolhe:= 1;
    podeFalar := true;
    repeat
        telaFolheiaCarbono (folheiaNumItens);
        folheiaExecuta (numFolhe, numFolhe, c, c2, podeFalar);
        if numFolhe < 1 then NumFolhe := 1;
        if numFolhe > folheiaNumItens then numFolhe := folheiaNumItens;
        sintPara;
        folheiaObtemItem (numFolhe, item, selecionado);
        deletaAspas (item);
        deletaMenorMaior (item);

        if c = #$0 then
            case c2 of
                ESQ: sintetiza (item);
                DIR: sintsoletra (item);
                F1: ajudaFolheCarbono;

                f5: numFolhe := procuraItem (numFolhe);
                CTLF5: numFolhe := procuraProximoItem(numFolhe);
                f8: falaHora;
                CTLF8: falaDia;
            end
        else
        case upcase(c) of
            ENTER:;
        ^R, ^A: numFolhe := apagaItensDoFolheamento (numFolhe);
            ^Q: falaQualItemDeQuantos (numFolhe, folheiaNumItens, false);
            ^S: falaQualItemDeQuantos (numFolhe, folheiaNumItens, true);
            ESC:;
        end;

        if folheiaNumItens <= 0 then
            begin
                msgBaixo ('CTLICAVA'); {'Lista de copias carbono vazia.'}
                goto fim;
            end;

        if (upCase(c) in[^Q, ^S]) or (c2 in [ESQ, DIR, f8, CTLF8]) then
            podeFalar := false
        else
            podeFalar := true;

        if (upcase (c) in ['A'..'Z']) or (upcase (c) in ['0' .. '9']) then
            begin
                i := numFolhe + 1;
                if i > folheiaNumItens then i := folheiaNumItens;
                folheiaObtemItem (i, item, selecionado);
                deletaAspas (item);
                deletaMenorMaior (item);
                while (i <> numFolhe) and  (maiuscAnsi (item[1]) <> upcase(c)) do
                    begin
                        if i >= folheiaNumItens then
                            i := 1
                        else
                            i := i + 1;
                        folheiaObtemItem (i, item, selecionado);
                        deletaAspas (item);
                        deletaMenorMaior (item);
                    end;
                if maiuscAnsi (item[1]) = upcase(c) then
                    numFolhe := i;
            end;

    until c = ESC;

fim:
//A baixo, instruções para tirar da lista os apagados
    limpaListaCarbono (pt);
    for i := 1 to folheiaNumItens do
        begin
            folheiaObtemItem (i, item, selecionado);
            new (pCarb);
            with pCarb^ do
                begin
                    nome := item;
                    prox := pt;
                    pt := pCarb;
                end;
        end;
    inverteListaCC (pt);

    folheiaDestroi;
    textColor (WHITE);
    telaPrincipal;
end;

{-------------------------------------------------------------}
{       Copias carbono para todos na resposta da carta
{-------------------------------------------------------------}

function  respondeTodosCC (nCar: integer): boolean;
var
    c, c2: char;
begin
    pCc := NIL;
    pBcc := NIL;
    respondeTodosCC := true;
    extraiCc (nCar);
    if pCC = NIL then exit;

    repeat
        textBackground (RED);
        mensagem ('CTRSPOUT', 1);  {'A carta a que você está respondendo tinha sido enviada a outras pessoas'}
        delay (100);
        mensagem ('CTENVIAT', 0);  {'Quer enviar sua resposta também para elas ? '}
        sintLeTecla (c, c2);
        textBackground (BLACK);
        writeln;
        if (c = #0) and ((c2 = CIMA) or (c2 = BAIX)) then
            folheiaCopiasCarbono ( pCC);

        if pCC = NIL then exit;
    until upcase (c) in ['S', 'N', ENTER, ESC];
    if upcase (c) in ['N', ESC] then limpaListaCarbono (pCC);
    if c = ESC then respondeTodosCC := false; //Cancela o preparo da carta para envio
end;

{-------------------------------------------------------------}
{       Lista as cópias carbono.
{-------------------------------------------------------------}

procedure  listarCopiasCarbono (nCar: integer);
begin
    pCc := NIL;
    pBcc := NIL;
    extraiCc (nCar);
    if pCC <> NIL then
        begin
            folheiaCopiasCarbono ( pCC);
            limpaListaCarbono (pCC);
        end
    else
        sintBip;
end;

{-------------------------------------------------------------}
begin
end.
