O objectivo do trabalho final é o desenvolvimento de um programa
que permita a edição de documentos simples. Entende-se por
documento neste trabalho uma sequência de parágrafos, consistindo cada
parágrafo numa sequência de glifos de tipos variados, bem como a sequência
das acções que levaram ao seu estado presente. O trabalho
deverá ser realizado em Linux, fazendo uso dos pacotes Slang++
e
Pacotes
, fornecidos pelos docentes. Estes pacotes estão
instalados na máquina mercurio
*.
Consulte a documentação (Manual do Slang++ em linha ou em
PDF e Manual
do Pacotes em linha ou em PDF).
* Se desejar usar os pacotes em casa deve instalá-los seguindo as instruções incluídas no Manual do Slang++ e no Manual do Pacotes.
Esta secção do enunciado poderá ser actualizada se surgirem esclarecimentos importantes acerca do enunciado original ou se os docentes pretenderem dar "dicas" de resolução.
Esclarecimentos:
Recomendações:
A unidade básica de constituição dos documentos a editar é o glifo. Existem três tipos concretos de glifos a representar:
:-)
;-)
:-(
:-|
:-D
:-*
:-X
:-P
:o)
:O)
;-(
:-o
:-O
O:-)
>:->
>:-)
:->
8-)
:-\
:-/
=|:-)
<:o}
Na Figura 1 encontra exemplos visuais destes tipos de glifos. Na primeira linha encontra apenas caracteres, na segunda apenas sorrisos e na terceira encontra sorrisos e caracteres emoldurados.
Figura 1: Exemplos de glifos.
Os glifos dividem-se em quebráveis e não-quebráveis. Um glifo quebrável possibilita a divisão de um parágrafo em várias linhas para efeitos de visualização. Os glifos quebráveis podem ter três comportamentos:
Um parágrafo é simplesmente uma qualquer sequência de glifos. A sequência pode estar vazia, i.e., não conter nenhum glifo.
A posição do cursor faz parte integrante da definição de cada parágrafo. A posição do cursor será útil durante a edição e indica qual o glifo corrente do parágrafo. Este cursor pode-se localizar sobre qualquer glifo do parágrafo ou sobre um glifo fictício final, inexistente (um pouco como acontecia no caso das listas). Deslocamentos do cursor correspondem a acções realizadas sobre o documento (ver Secções 1.3.1 e 2.5).
Um documento é uma sequência de parágrafos. Existe sempre pelo menos um parágrafo num documento. Existe um cursor de parágrafo, que indica qual o parágrafo corrente. Este cursor apenas se pode localizar sobre parágrafos existentes.
Faz também parte do documento a lista das acções efectuadas para o constituir no seu estado actual. Em teoria um documento é reconstituível na íntegra a partir desta lista de acções.
Todas as acções que levaram a alguma alteração do documento devem ser guardadas numa lista. Este facto permite em qualquer ocasião da vida do documento, desfazer as acções sucessivamente até se obter o documento inicial, contendo apenas um parágrafo vazio. As acções desfeitas podem ser refeitas, pelo que a posição na lista das acções da última acção desfeita faz também parte do documento. Normalmente não existem quaisquer acções desfeitas na lista das acções, pelo que esta posição se refere a uma acção fictícia final, inexistente.
Os documentos podem ser guardados e carregados a partir de ficheiros de texto. Cada ficheiro devem conter toda a informação do respectivo documento, incluindo a lista das acções que o produziu. Não há qualquer formato pré-definido para os ficheiros.
Está disponível na máquina mercurio
, (no directório /usr/local/bin
)
uma versão executável do programa (chamada editor-oficial
)
que lhe possibilitará experimentar à medida que for lendo o enunciado.
Não se esqueça que o nome do programa fornecido pelos docentes
é editor-oficial,
pelo que não deverá usar esse nome
para o seu próprio programa.
O executável está disponível quer para RedHat 6.2 quer para RedHat 7.0.
editor
. Este deve
poder ser invocado de uma de duas formas.
A primeira forma de invocação é:
Neste caso o editor deve começar por ler o documento guardado no ficheiro
./editor doc1
doc1
. Caso não seja possível a leitura deste documento o editor
arranca com um documento vazio (ou melhor, com um só parágrafo vazio).
A segunda forma invocação é:Experimente o comando acima, mas escrevendo
editor-oficial
em vez de./editor
, de modo a usar a resolução oficial. Para sair do editor pressione 'f10'.
Neste caso o editor começa com um documento vazio que não está associado a nenhum ficheiro.
./editor
Experimente o comando acima (mas com
editor-oficial
, não se esqueça!).
O documento deverá ser visualizado parágrafo por parágrafo. A apresentação de cada parágrafo começa na primeira coluna do ecrã, sendo se necessário justificado à esquerda ao longo de várias linhas. A última coluna do ecrã é reservada para colocar o cursor em situações especiais. Os parágrafos deverão ser reformatados no ecrã sempre que a dimensão do ecrã mudar (deve-se sempre considerar que a largura mínima do ecrã é de duas colunas, mesmo quando tal não suceder na realidade). Os parágrafos são divididos pelas várias linhas apenas em glifos quebráveis. Os glifos quebráveis são o espaço (' ') e o hífen ('-'). Os espaços desaparecem quando quebrados, enquanto os hífens são reproduzidos em ambas as linhas.
Experimente com
editor-oficial
introduzir algum texto (incluindo hífens) e redimensionar o ecrã de modo a verificar o tipo de ajustamentos necessários.
Cada linha é desenhada tão próximo quanto possível da linha acima, mas considerando o facto de poderem haver nas linhas glifos que se prolongam para cima e para baixo da linha base.
Emoldure alguns glifos existentes ('ctrl-e'), e redimensione o ecrã de modo a verificar o tipo de ajustamentos realizados. Pode emoldurar uma moldura, para aumentar a sua altura.
Quando não for possível quebrar uma linha de modo a que ocupe apenas a largura do ecrã disponível (menos a coluna final, que é reservada), o editor deve quebrar a linha no primeiro local disponível e desenhá-la mesmo fora dos limites permitidos e fora do ecrã físico.
Experimente reduzir a largura do ecrã até que haja zonas inquebráveis do texto e veja o que acontece.
Por omissão o documento começa a ser visualizado na primeira linha do ecrã. Aliás, a primeira linha do primeiro parágrafo do documento nunca poderá ser mostrada abaixo da primeira linha do ecrã. É possível visualizar documentos extensos usando os comandos 'ctrl-a' (página anterior) e 'ctrl-p' (próxima página), que fazem evoluir a zona visualizada do documento para cima ou para baixo, de acordo com a altura corrente do ecrã.
Experimente introduzir um texto extenso (pode partir ou abrir novos parágrafos usando 'enter') e usar os comandos 'ctrl-a' e 'ctrl-p' para recuar ou avançar a zona visualizada dos mesmos..
A zona visualizada dos documentos pode ou não conter o cursor (ver abaixo). É claro que esta não é uma característica desejável do editor, mas simplifica a sua implementação.
Verifique este facto no editor oficial.
O cursor do editor indica qual o glifo corrente do parágrafo corrente. Na realidade o cursor do editor é uma abstracção. Cada parágrafo mantém o seu próprio cursor, que indica o glifo corrente nesse parágrafo, e existe um cursor de parágrafo, que indica qual o parágrafo corrente do documento. O cursor do editor corresponde, portanto, ao cruzamento do cursor de parágrafo com o cursor de glifo do parágrafo corrente. O cursor do editor é representado visualmente dando uma cor diferente ao glifo em causa (que pode ter mais do que uma célula do ecrã).
Crie um glifo emoldurado e desloque o cursor de modo a passar sobre ele.
O cursor deve poder ser deslocado usando as teclas com setas (cima/baixo e esquerda/direita). Deslocar o cursor para cima e para baixo tem como efeito recuar ou avançar no parágrafo corrente do documento. A posição do cursor em cada parágrafo é independente. Este facto pouco conveniente destina-se a simplificar a implementação do programa.
O cursor pode ser deslocado para fora da área visível do ecrã! Quando o cursor se encontra no glifo fictício final de um parágrafo deve ser mostrado como se de um espaço se tratasse. Quando o cursor se encontrar sobre um espaço quebrado, esse espaço deve ser mostrado, mesmo que para isso a largura da linha exceda o limite "legal".
Experimente deslocar o cursor ao longo de uma documento com vários parágrafos. Verifique todos os factos apontados.
Descrevem-se brevemente as acções que se podem realizar sobre o documento. Acções são comandos que alteram o documento. Os comandos que não alteram o documento são descritos mais abaixo. Nem sempre se podem fazer determinadas acções. Quando tal suceder ocorre um aviso sonoro e o documento permanece inalterado.
Vá sempre experimentando as acções descritas no editor oficial.
Premir as setas altera o parágrafo corrente (setas para cima e para baixo) ou o glifo corrente do parágrafo corrente (setas para a esquerda e direita).
Erros:
Premir um caractere gráfico tem como resultado inserir o respectivo glifo antes do glifo corrente do parágrafo corrente (o efeito visual é o de "empurrar" os glifos a partir do cursor para a direita).
Erros: Nenhum.
Premir 'ctrl-s' faz surgir um menu onde se pode escolher um sorriso a inserir como glifo antes do glifo corrente do parágrafo corrente.
Erros: Nenhum.
Premir 'del' remove o glifo corrente do parágrafo corrente. O cursor do parágrafo corrente desloca-se para o glifo imediatamente à direita do glifo removido (que pode ser fictício).
Erros: Tentar remover o glifo fictício final do parágrafo corrente.
Premir 'ctrl-e' emoldura o glifo corrente do parágrafo corrente.
Erros: Tentar emoldurar o glifo fictício final do parágrafo corrente.
Premir 'ctrl-d' retira a moldura ao glifo corrente do parágrafo corrente.
Erros: Tentar desemoldurar o glifo fictício final do parágrafo corrente ou um glifo que não está emoldurado.
Premir 'enter' parte em dois o parágrafo corrente. O primeiro parágrafo fica com todos os glifos até ao glifo corrente (exclusive) e o segundo fica com todos os glifos a partir daí. Dependendo da posição do cursor no parágrafo corrente, qualquer dos parágrafos resultantes pode estar vazio. O parágrafo corrente passa a ser o segundo parágrafo gerado. O glifo corrente do primeiro parágrafo passa a ser o glifo fictício final. O glifo corrente do segundo parágrafo passa a ser o primeiro glifo (se existir, senão será o glifo fictício final).
Erros: Nenhum.
Premir 'ctrl-j' junta o parágrafo corrente com o que se lhe segue. Os glifos de um e outro são simplesmente concatenados, não se acrescentando qualquer espaço entre eles. O glifo corrente mantém-se o do primeiro parágrafo, excepto se fosse o glifo fictício final, caso em que passa a ser o primeiro glifo junto do segundo parágrafo (entretanto desaparecido).
Erros: Esta acção não faz sentido se o parágrafo corrente for o último do documento.
Incluem-se aqui descrições de comandos que alteram o documento ou que, fazendo-o, não são em si passíveis de serem desfazíveis ou refazíveis. É o caso justamente dos comandos de desfazer e refazer.
Premir 'ctrl-a' mostra o ecrã anterior do documento.
Erros: Este comando não faz sentido se a primeira linha do primeiro parágrafo do documento já estiver visível no ecrã. Em nenhum caso essa linha poderá ser mostrada abaixo da primeira linha do ecrã.
Premir 'ctrl-p' mostra o próximo ecrã do documento.
Erros: Este comando não faz sentido se a última linha do último parágrafo do documento já estiver visível na primeira linha do ecrã. Em nenhum caso essa linha poderá ser mostrada acima da primeira linha do ecrã.
Premir 'ctrl-z' desfaz a última acção feita sobre o documento. Embora desfazer seja considerado um comando e não um acção, afecta o documento. É possível desfazer todas as acções realizadas até ao documento original com apenas um parágrafo vazio.
Premir 'ctrl-x' refaz a última acção desfeita sobre o documento. Embora refazer seja considerado um comando e não um acção, afecta o documento. É possível refazer todas as acções desfeitas anteriormente. Tem por isso o efeito contrário ao do comando de desfazer. Realizar uma acção após uma sequência de comandos de desfazer elimina a possibilidade de os refazer.
Premir 'ctrl-l' refresca o ecrã. I.e., força-o a ser redesenhado. Existe prevendo erros do programa na visualização do documento ou interferência de programas externos no estado do ecrã.
Premir 'f10' sai da edição do documento. O editor começa por perguntar se o utilizador pretende guardar o documento (esta pergunta é feita mesmo que o documento não tenha sofrido alterações). Se a resposta for negativa, o programa termina. Se a resposta for positiva:
Se houver problemas na criação do ficheiro em qualquer destes casos, o programa permite ao utilizador introduzir nomes alternativos.
Se existirem erros durante a gravação do ficheiro, apesar de ter sido possível estabelecer um canal para ele, o programa avisa desse facto e termina sem guardar (pouco conveniente, mas simplifica a implementação).
Devem produzir um aviso sonoro e não ter efeito.
Dúvidas acerca da interface do editor devem ser esclarecidas recorrendo ao editor oficial, à secção de Esclarecimentos e Recomendações, à lista de correio electrónico da disciplina (poo-iscte@yahoogroups.com), ou aos docentes da disciplina.
carregaDe()
(que carrega nova
informação a partir de um canal de entrada) e guardaEm()
(que
guarda num canal de saída toda a informação).A resolução integral deste enunciado está cotada para 24 valores, embora a nota final não possa exceder os 20 valores, como é natural. É possível eliminar parte dos requisitos funcionais com as seguinte penalizações:
.C
, ._impl.H
e .H
) e o respectivo ficheiro de
construção (Makefile
);Courier
) e, caso seja possível fazê-lo,
imprima em papel reciclado, frente-e-verso.Os horários das orais e a forma de inscrição serão anunciados logo que possível.
A nota deste trabalho será dada apenas após uma discussão, individual, com cada um dos elementos do grupo. Nesta discussão qualquer elemento do grupo terá de demonstrar um total conhecimento do programa e ser capaz de operar as alterações que forem pedidas. Nessa oral serão também feitas perguntas sobre a matéria em geral. A nota final dependerá não só da qualidade do trabalho, mas também, e principalmente, do conhecimento do programa e da matéria em geral e da capacidade de resolver problemas em C++ demonstrados nessa discussão.
Slang++
Slang++
apresenta
algumas complicações. Acontece que estas aplicações
não podem ser executadas dentro do depurador, pois fazem uso de
capacidades do terminal que este não disponibiliza. Assim,
é necessário executar o programa a depurar numa janela xterm
normal, fora do gdb
, e depois convencer o gdb
a "agarrar-se"
ao programa já em execução. Para isso:
gdb
dentro do Emacs
, como habitualmente, especificando
o ficheiro a depurar. Não dê o comando r[un]
!xterm
.ps -auxww | grep nome_do_programa | grep annnnn
nnnnn
é o seu número de aluno e nome_do_programa
é o nome do programa a depurar. Surgir-lhe-á uma lista
dos processos que são instâncias do seu programa e que lhe
pertencem. É conveniente que tenha apenas um programa em execução
de modo a identificar claramente qual o PID que lhe interessa.
gdb
coloque um ponto de paragem onde for conveniente.
Em seguida dê o comando:attach pid
pid
é o PID do processo identificado na alínea
anterior. Este comando faz com que o gdb
passe a controlar
o processo. Dê o comando:
c[ontinue]