MEMOEDIT()
 Exibe ou edita cadeias de caracteres e campos memo
------------------------------------------------------------------------------

 Sintaxe

     MEMOEDIT([<cString>],
        [<nTopo>], [<nEsquerda>],
        [<nBase>], [<nDireita>],
        [<lModoEdiçao>],
        [<cFunçaoControle>],
        [<nTamanhoLinha>],
        [<nTamanhoTab>],
        [<nLinhaBufferTexto>],
        [<nColunaBufferTexto>],
        [<nLinhaJanela>],
        [<nColunaJanela>]) --> cBufferTexto

 Argumentos

     <cString> é a cadeia de caracteres ou campo memo a ser copiado para
     o buffer de texto da MEMOEDIT().  Caso nao seja especificado, o buffer
     de texto fica vazio.

     <nTopo>, <nEsquerda>, <nBase>, e <nDireita> sao as
     coordenadas superior esquerda e inferior direita da janela.  Valores de
     linha podem variar de zero a MAXROW(), e posiçoes de coluna podem
     variar de zero a MAXCOL().  Se nao forem especificadas, as coordenadas
     padrao sao 0, 0, MAXROW(), e MAXCOL().

     <lModoEdiçao> determina se o buffer de texto pode ser editado ou
     simplesmente exibido.  Especificar verdadeiro (.T.) permite ao usuário
     fazer alteraçoes no buffer de texto, enquanto que especificar falso
     (.F.) permite ao usuário somente a leitura do buffer de texto.  Caso
     nao seja especificado, o valor padrao é verdadeiro (.T.).

     <cFunçaoControle> é o nome de uma funçao de usuário que é executada
     quando o usuário pressionar uma tecla nao reconhecida pela MEMOEDIT() e
     quando nao houver teclas pendentes no buffer de teclado.
     <cFunçaoControle> é especificada como um valor caractere sem parênteses
     ou argumentos.  Especificando-se falso (.F.) neste argumento, o
     <cString> é exibido, e a MEMOEDIT() é terminada.  Caso este argumento
     seja especificado, o comportamento automático da MEMOEDIT() é
     alterado.

     <nTamanhoLinha> determina o tamanho das linhas exibidas na janela
     da MEMOEDIT().  Caso exista uma linha maior do que <nTamanhoLinha>, ela
     é transportada para  a próxima linha na janela de MEMOEDIT().  Se
     <nTamanhoLinha> for maior do que o número de colunas na janela de
     MEMOEDIT(), a janela de ediçao será deslocada caso o cursor se mova
     para além do limite da janela.  Se <nTamanhoLinha> nao for
     especificado, o tamanho de linha padrao é (<nDireita> - <nEsquerda>).

     <nTamanhoTab> determina o tamanho de um caractere de tabulaçao a
     ser inserido quando o usuário pressionar Tab.  Caso <nTamanhoTab> nao
     seja especificado, sao inseridos quatro espaços ao invés de um
     caractere de tabulaçao.

     <nLinhaBufferTexto> e <nColunaBufferTexto> definem a posiçao de
     exibiçao do cursor dentro do buffer de texto quando é invocada a
     MEMOEDIT().  <nLinhaBufferTexto> começa com 1 (um) e
     <nColunaBufferTexto> começa com zero.  Se estes argumentos nao forem
     especificados, o cursor é posicionado na linha 1 (um) e coluna zero da
     janela de MEMOEDIT().

     <nLinhaJanela> e <nColunaJanela> definem a posiçao inicial do
     cursor dentro da janela da MEMOEDIT().  Posiçoes de linha e coluna
     começam com zero.  Caso estes argumentos nao sejam especificados, a
     posiçao inicial na janela é linha zero mais a posiçao de coluna onde o
     cursor estiver.

 Retorno

     MEMOEDIT() retorna o buffer de texto caso o usuário termine a ediçao
     com Ctrl-W, ou uma cópia de <cString> caso o usuário termine com Esc.

 Descriçao

     MEMOEDIT() é uma funçao de interface com o usuário e de ediçao de
     textos, que pode ser utilizada para editar campos memo e cadeias de
     caracteres longas.  A ediçao ocorre dentro de uma regiao de janela
     especificada, posicionada em qualquer lugar na tela.  Da mesma forma
     que outras funçoes de interface com o usuário (ACHOICE(), DBEDIT()),
     MEMOEDIT() suporta uma série de modos distintos, e inclui uma funçao de
     usuário para permitir a reconfiguraçao de teclas e outras atividades
     relevantes à programaçao da tarefa de ediçao de textos.

       O buffer de texto: Quando é invocada a MEMOEDIT() e é
        especificado <cString>, <cString> é copiado para o buffer de texto.
        O buffer de texto é o que o usuário realmente edita.  Caso nao seja
        especificado <cString>, é apresentado ao usuário um buffer de texto
        vazio para ediçao.

        Quando o usuário sai da MEMOEDIT() pressionando Ctrl-W, o conteúdo
        do buffer de texto é retornado.  Se o usuário sair pressionando Esc,
        o buffer de texto é descartado e o valor original de <cString> é
        retornado.  De qualquer maneira, o valor retornado pode entao ser
        atribuido a uma variável ou campo memo, ou passado como um argumento
        para outra funçao.

       Modos de Ediçao: MEMOEDIT() suporta dois modos de ediçao,
        dependendo do valor de <lModoEdiçao>.  Quando <lModoEdiçao> é
        verdadeiro (.T.), MEMOEDIT() entra no modo de ediçao, e ao usuário é
        permitido alterar o conteúdo do buffer de texto da MEMOEDIT().
        Quando <lModoEdiçao> é falso (.F.), MEMOEDIT() entra no modo
        visualizar, e ao usuário é permitido navegar pelo buffer de texto,
        mas sem editar ou inserir textos.  Para facilitar a visualizaçao
        para o usuário, é desabilitado a rolagem, fazendo com que as teclas
        Cursor para cima e Cursor para baixo naveguem uma linha para cima ou
        para baixo no buffer de texto dentro da janela de MEMOEDIT().

       Entrando e editando textos: Dentro da MEMOEDIT(), o
        usuário pode entrar e editar textos posicionando o cursor,
        adicionando, ou eliminando caracteres.  Para facilitar a ediçao de
        textos, há uma série de teclas de navegaçao e ediçao:

        Tabela 5-20: Teclas de Navegaçao e Ediçao em MEMOEDIT()
        ---------------------------------------------------------------------
        Tecla                            Açao
        ---------------------------------------------------------------------
        Cursor para cima/Ctrl-E          Move para cima uma linha
        Cursor para baixo/Ctrl-X         Move para baixo uma linha
        Cursor para esquerda/Ctrl-S      Move para esquerda um caractere
        Cursor para direita/Ctrl-D       Move para direita um caractere
        Ctrl-Cursor para esquerda/Ctrl-A Move para esquerda uma palavra
        Ctrl-Cursor para direita/Ctrl-F  Move para direita uma palavra
        Home                             Move para o início da linha corrente
        End                              Move para o final da linha corrente
        Ctrl-Home                        Move para o início da janela
                                         corrente
        Ctrl-End                         Move para o final da janela corrente
        PgUp                             Move para janela anterior
        PgDn                             Move para a próxima janela
        Ctrl-PgUp                        Move para o início do texto
        Ctrl-PgDn                        Move para o final do texto
        Return                           Move para o início da próxima linha
        Del                              Elimina caractere onde está o cursor
        Backspace                        Elimina caractere à esquerda do
                                         cursor
        Tab                              Insere tab ou espaços
        Caracteres Imprimíveis           Insere caractere
        Ctrl-Y                           Elimina a linha corrente
        Ctrl-T                           Elimina a palavra à direita
        Ctrl-B                           Reformata parágrafo
        Ctrl-V/Ins                       Comuta modo de inserçao
        Ctrl-W                           Grava e finaliza a ediçao
        Esc                              Aborta ediçao e retorna o original
        ---------------------------------------------------------------------

       A tela de ediçao: Quando MEMOEDIT() exibe, ela
        sobreescreve a área especificada da tela e nao grava a tela
        original.  Além disso, ela nao exibe bordas nem títulos.  Para
        fornecer estas ferramentas, você deve criar uma rotina ou funçao de
        usuário que execute estas açoes e depois chame a MEMOEDIT().  Veja o
        exemplo abaixo.

       A funçao de controle: A funçao de controle é especificada
        no argumento <cFunçaoControle>, que manipula exceçoes de tecla e
        reconfigura teclas especiais.  A funçao de controle é chamada várias
        vezes pela MEMOEDIT(), muito frequentemente em resposta a teclas que
        ela nao reconhece.  Teclas que causam uma exceçao sao todas as
        teclas Alt, de funçao, e teclas de controle disponíveis.  Como estas
        teclas nao sao processadas pela MEMOEDIT(), elas podem ser
        reconfiguradas.  Algumas destas teclas têm uma açao padrao atribuida
        às mesmas.  Na funçao de controle, você executa várias açoes que
        dependem do modo corrente da MEMOEDIT() e depois Retorna um valor
        que diz à MEMOEDIT() o que fazer.

        Quando o argumento funçao de controle é especificado, MEMOEDIT()
        define duas classes de teclas: nao configuráveis e exceçoes de
        tecla.  Quando é pressionada uma tecla nao configurável, MEMOEDIT()
        a executa; caso contrário é gerada uma exceçao de tecla e a funçao
        de controle é chamada.  Quando nao houver mais nenhuma tecla
        pendente no buffer de teclado a ser processada pela MEMOEDIT(), a
        funçao de controle é chamada novamente.

        Quando a MEMOEDIT() chama a funçao de controle, ela automaticamente
        passa parâmetros indicando o modo da MEMOEDIT(), a linha corrente no
        buffer de texto, e a coluna corrente no buffer de texto.  O modo
        indica o estado atual da MEMOEDIT(), dependendo da última açao
        tomada antes da execuçao da funçao de controle.  Sao possíveis os
        seguintes modos:

        Tabela 5-21: Modos de MEMOEDIT()
        ---------------------------------------------------------------------
        Modo           Memoedit.ch          Descriçao
        ---------------------------------------------------------------------
        0              ME_IDLE              Inativo, todas as teclas foram
                                            processadas
        1              ME_UNKEY             Tecla desconhecida, memo
                                            inalterado
        2              ME_UNKEYX            Tecla desconhecida, memo alterado
        3              ME_INT               Modo de inicializaçao
        ---------------------------------------------------------------------

        Um valor de modo 3 indica que a MEMOEDIT() está em modo de
        inicializaçao.  Quando você especifica a <cFunçaoControle>,
        MEMOEDIT() faz uma chamada à funçao de controle imediatamente após
        ser invocada.  Neste ponto, você retorna uma solicitaçao de
        configuraçao dos vários modos de formataçao de texto da MEMOEDIT():
        transporte, rolagem, ou inserir.  MEMOEDIT() chama a funçao de
        controle repetidamente, permanencendo no modo de inicializaçao até
        que você retorne 0.  O buffer de texto é entao exibido, e o controle
        entra no modo de ediçao configurado por <lModoEdiçao>.  Observe que
        se o transporte estiver ativo quando MEMOEDIT() mudar do modo de
        inicializaçao para o de ediçao, todo o buffer de texto é formatado
        com <nTamanhoLinha>.  Para evitar esta formataçao inicial, desligue
        o transporte durante a inicializaçao.  Observe também que a ativaçao
        ou nao de transporte e rolagem nao é atribuida a nenhuma tecla,
        porém isto pode ser feito a partir da funçao de controle.

        Os modos 1 e 2 indicam que a MEMOEDIT() capturou uma tecla nao
        reconhecida ou configurável do buffer de teclado.  Teclas
        configuráveis sao processadas retornando-se 0 para que seja
        executada a açao padrao da MEMOEDIT().  O retorno de um valor
        diferente executa outra açao de tecla, desta forma redefinindo a
        tecla.  Caso seja uma tecla nao reconhecida, você pode definir uma
        açao para ela retornando um valor que solicita uma açao de tecla ou
        executa uma açao que você mesmo definiu.

        O modo 0 indica que a MEMOEDIT() encontra-se inativa, e nenhuma
        tecla falta ser processada.   Sempre que isto acontecer, a
        MEMOEDIT() faz uma chamada à funçao de controle.  Neste ponto, você
        geralmente atualiza exibiçoes de número de linha e coluna.

        Os outros dois parâmetros, linha corrente e coluna, indicam a
        posiçao corrente do cursor no buffer de texto quando a funçao de
        controle é chamada.  O parâmetro linha começa com posiçao 1 (um), e
        coluna começa com posiçao zero.

        Quando o modo é 1, 2 ou 3, você pode retornar um valor que instrui a
        MEMOEDIT() qual a próxima açao a ser executada.  A tabela a seguir
        resume os valores de retorno possíveis e suas
        consequências:

        Tabela 5-22: Valores de Retorno da Funçao de Controle de MEMOEDIT()
        ---------------------------------------------------------------------
        Valor             Memoedit.ch             Açao
        ---------------------------------------------------------------------
        0                 ME_DEFAULT              Executa açao padrao
        1-31              ME_UNKEY                Processa açao
                                                  correspondente ao valor da
                                                  tecla
        32                ME_IGNORE               Ignora tecla
        33                ME_DATA                 Trata tecla como dado
        34                ME_TOGGLEWRAP           Comuta modo de transporte
        35                ME_TOGGLESCROLL         Comuta modo de rolagem
        100               ME_WORDRIGHT            Próxima palavra
        101               ME_BOTTOMRIGHT          Base da tela
        ---------------------------------------------------------------------

       Arquivos header: Para que os valores de modo e
        solicitaçao sejam mais fáceis de ser lembrados e utilizados, é
        fornecido o arquivo Memoedit.ch no \CLIPPER5\INCLUDE.  Além disso,
        Inkey.ch está localizado no mesmo diretório, e contém constantes
        para todos os valores INKEY().

 Notas

       Configurando teclas: Se a <cFunçoUsuário> for
        especificada, as teclas na tabela abaixo sao
        configuráveis.  Se a tecla for reconfigurável,
        retornar 0 executa a açao padrao da MEMOEDIT().  retornar um valor
        diferente, porém, executa outra açao de tecla, desta forma
        redefinindo a mesma.  Caso a tecla nao seja do tipo configurável
        reconhecido pela MEMOEDIT(), você pode definir uma açao para ela
        também retornando um valor que pede uma açao de tecla da tabela
        abaixo.

        Tabela 5-23: Teclas Configuráveis em MEMOEDIT()
        ---------------------------------------------------------------------
        Tecla                Açao Padrao
        ---------------------------------------------------------------------
        Ctrl-Y               Elimina a linha corrente
        Ctrl-T               Elimina a palavra à direita
        Ctrl-B               Reformata parágrafo
        Ctrl-V/Ins           Comuta modo de inserçao
        Ctrl-W               Finaliza ediçao e grava
        Esc                  Aborta ediçao e retorna original
        ---------------------------------------------------------------------

       Transporte: Transporte é um modo de formataçao que você
        pode alternar se retornar 34 da funçao de usuário.  Quando está on
        (o padrao), MEMOEDIT() insere um soft carriage return/line feed
        (retorno automático) ao final da palavra mais próxima da borda da
        janela ou tamanho de linha, valendo o que ocorrer primeiro.  Quando
        transporte está desligado, MEMOEDIT() rola o buffer de texto para
        além dos limites da janela até que o cursor atinja o final da
        linha.  Neste ponto, o usuário deve pressionar Return (inserindo um
        hard carriage return/line feed) para avançar para a próxima linha.

       Alterando parágrafos: Pressionar Ctrl-B ou retornar 2 de
        uma funçao de usuário causa a reformataçao do buffer de texto até
        que um hard carriage return (final de parágrafo) ou o final do
        buffer de texto seja alcançado.  Isto acontece sem importar se
        trabsporte está ligado ou desligado.

       Carriage returns automáticos: Carriage returns
        automáticos podem interferir na exibiçao de comandos de console tais
        como ? e REPORT FORM, ou o processamento com outro processador de
        textos.  Use HARDCR(), MEMOTRAN(), ou STRTRAN() para substituir
        estes caracteres, conforme sua necessidade.

       Editando arquivos texto: MEMOEDIT() pode ser utilizada
        para editar arquivos texto se o arquivo texto puder ser lido para
        uma variável caractere Clipper.  Isto pode ser feito com a funçao
        MEMOREAD().  Após a ediçao do conteúdo do arquivo texto contido na
        variável caractere, ele pode ser escrita no arquivo novamente com
        MEMOWRIT().

 Exemplos

       O exemplo a seguir permite ao usuário visualizar um campo
        memo, sem deixar que sejam feitas alteraçoes no buffer de texto:

        USE Customer NEW
        SET CURSOR OFF
        MEMOEDIT(CustNotes, 5, 10, 20, 69, .F.)
        SET CURSOR ON

       Este exemplo ilustra como permitir ao usuário editar um campo
        memo, sendo que depois estas alteraçoes serao atribuidas ao campo
        memo:

        USE Customer NEW
        REPLACE CustNotes WITH MEMOEDIT(CustNotes, 5, 10, 20, 69)

       Este exemplo demonstra como criar uma cadeia de caracteres
        usando MEMOEDIT():

        LOCAL cNotes
        cNotes = MEMOEDIT()


       Este exemplo demonstra uma funçao definida pelo usuário que
        edita uma cadeia de caracteres em uma janela com moldura exibida com
        um título:

        FUNCTION MemoEdit( cString, cTítulo, nTop, nLeft, nBottom, nRight )
           LOCAL cTela := SAVESCREEN(nTop, nLeft, nBottom, nRight)
           @ nTop - 1, nLeft - 2 CLEAR TO nBottom + 1, nRight + 2
           @ nTop - 1, nLeft - 2 TO nBottom + 1, nRight + 2
           @ nTop - 1, nLeft SAY "[" + cTitle + "]"
           cString = MEMOEDIT(cString, nTop, nLeft, nBottom, nRight)
           RESTSCREEN(nTop, nLeft, nBottom, nRight, cTela)
           RETURN (cString)

      O exemplo a seguir lê o conteúdo de um arquivo texto para uma
        variável caractere, edita, e depois escreve o novo conteúdo no
        disco:

        LOCAL cString := MEMOREAD("Text.txt")
        cString := MEMOEDIT(cString)
        IF !MEMOWRIT("Text.txt", cString)
           ? "Erro de gravacao"
           BREAK
        ENDIF
        RETURN

 Arquivos:  Biblioteca EXTEND.LIB, arquivos header Memoedit.ch, Inkey.ch.
 To download this example - click here.

See Also: LASTKEY() MEMOREAD() MEMOTRAN() MEMOWRIT()