Página principal   Módulos   Lista de namespaces   Hierarquia de classes   Lista de componentes   Lista de ficheiros   Membros do namespace   Componentes membro   Ficheiros membro   Páginas relacionadas  

ecra.C

Ir para a documentação deste ficheiro.
00001 
00007 #include <Slang++/ecra.H>
00008 
00009 #include <Utilitarios/ignoradores.H>
00010 #include <Erros/erros.H>
00011 
00012 using namespace std;
00013 
00014 // Posicao:
00015 
00016 Slang::Posicao::Posicao(istream& entrada) 
00017 {
00018     assert(entrada.good());
00019 
00020     entrada >> linha_ >> Utilitarios::il >> coluna_ >> Utilitarios::il;
00021 
00022     if(not entrada.good())
00023         throw Erros::ErroAoCarregar("Posicao");
00024 
00025     assert(cumpreInvariante());
00026 }
00027 
00028 void Slang::Posicao::guardaEm(ostream& saida) const
00029 {
00030     assert(cumpreInvariante());
00031 
00032     if(not (saida << linha_ << endl << coluna_ << endl))
00033         throw Erros::ErroAoGuardar("Posicao");
00034 }
00035 
00036 
00037 // Dimensao:
00038 
00039 Slang::Dimensao::Dimensao(istream& entrada) 
00040 {
00041     assert(entrada.good());
00042 
00043     entrada >> numero_de_linhas >> Utilitarios::il 
00044             >> numero_de_colunas >> Utilitarios::il;
00045 
00046     if(not entrada.good())
00047         throw Erros::ErroAoCarregar("Dimensao");
00048 
00049     assert(cumpreInvariante());
00050 }
00051       
00052 void Slang::Dimensao::guardaEm(ostream& saida) const
00053 {
00054     assert(cumpreInvariante());
00055 
00056     if(not (saida << numero_de_linhas << endl << numero_de_colunas << endl))
00057         throw Erros::ErroAoGuardar("Dimensao");
00058 }
00059 
00060 
00061 // Caixa:
00062 
00063 void Slang::Caixa::guardaEm(ostream& saida) const
00064 {
00065     assert(cumpreInvariante());
00066 
00067     origem_.guardaEm(saida);
00068     dimensao_.guardaEm(saida);
00069 }
00070 
00071 
00072 // Cor:
00073 
00074 istream& Slang::operator>>(istream& entrada, Slang::Cor& cor) 
00075 {
00076     string nome;
00077     if(entrada >> nome) {
00078         for(int c = Slang::primeira_cor; c != Slang::numero_de_cores; ++c)
00079             if(Slang::nomes_das_cores[c] == nome) {
00080                 cor = Slang::Cor(c);
00081 
00082                 return entrada;
00083             }
00084         entrada.clear(ios_base::badbit);
00085     }
00086 
00087     return entrada;
00088 }
00089 
00090 
00091 // Ecra:
00092 
00093 Slang::Ecra::Ecra(Cor cor_do_texto, Cor cor_do_fundo, 
00094                   bool cursor_deve_ser_limitado)
00095     : cursor_esta_limitado_ao_ecra_real(cursor_deve_ser_limitado),
00096       redimensionado_(false),
00097       cursor_imovel_na_proxima_operacao_de_escrita(false), 
00098       justificacao_actual(a_esquerda), 
00099       largura_da_proxima_operacao_de_escrita(0), 
00100       ocupacao_dos_objectos(ObjectoCor::numero_de_objectos_cor_no_s_lang) 
00101 {
00102     assert(not ja_existe_instancia);
00103 
00104     ja_existe_instancia = true;
00105 
00106     // Inicializações do slang:
00107 
00108     SLtt_get_terminfo();
00109 
00110     if(SLsmg_init_smg() == -1) {
00111         // Que fazer?
00112         assert(false);
00113     }
00114 
00115     // Inicialização do manipulador de mudanças no ecrã:
00116     SLsignal(SIGWINCH, manipuladorDeRedimensionamento);
00117 
00118     mudaCoresDasCelulasDoFundoPara(cor_do_texto, cor_do_fundo);
00119 
00120     assert(cumpreInvariante());
00121 }
00122 
00123 void Slang::Ecra::moveCursorPara(Posicao const& nova_posicao)
00124 {
00125     assert(cumpreInvariante());
00126 
00127     verificaRedimensionamento();
00128 
00129     int linha = nova_posicao.linha();
00130     int coluna = nova_posicao.coluna();
00131 
00132     if(cursor_esta_limitado_ao_ecra_real)
00133     {
00134         if(linha >= dimensao().numeroDeLinhas()) 
00135             linha = dimensao().numeroDeLinhas() - 1;
00136         else if(linha < 0) 
00137             linha = 0;
00138         
00139         if(coluna >= dimensao().numeroDeColunas()) 
00140             coluna = dimensao().numeroDeColunas() - 1;
00141         else if(coluna < 0) 
00142             coluna = 0;
00143     }
00144 
00145     SLsmg_gotorc(linha, coluna);
00146 
00147     assert(cumpreInvariante());
00148 }
00149 
00150 void Slang::Ecra::moveCursorDeAcordoCom(Slang::Tecla const& tecla) 
00151 {
00152     assert(cumpreInvariante());
00153     assert(tecla.eDeDeslocamento());
00154 
00155     switch(tecla)
00156     {
00157       case Tecla::cima:
00158         sobeCursor();
00159         break;
00160 
00161       case Tecla::baixo:
00162         baixaCursor();
00163         break;
00164 
00165       case Tecla::esquerda:
00166         recuaCursor();
00167         break;
00168 
00169       case Tecla::direita:
00170         avancaCursor();
00171         break;
00172 
00173       default:
00174         assert(false);
00175         break;
00176     }
00177 
00178     assert(cumpreInvariante());
00179 }
00180 
00181 Slang::Ecra::Troco const Slang::Ecra::trocoDe(Caixa const& caixa) const 
00182 {
00183     assert(cumpreInvariante());
00184     assert(caixa.eCanonica());
00185 
00186     verificaRedimensionamento();
00187 
00188     // Guardar cursor inicial:
00189     Posicao const posicao_original_do_cursor = posicaoDoCursor();
00190 
00191     int const linha = caixa.origem().linha(); 
00192     int const coluna = caixa.origem().coluna();
00193     int const numero_de_linhas = caixa.dimensao().numeroDeLinhas();
00194     int const numero_de_colunas = caixa.dimensao().numeroDeColunas();
00195 
00196     Troco troco(caixa.dimensao());
00197     int i = 0;
00198     for(int l = linha; l != linha + numero_de_linhas; ++l)
00199         for(int c = coluna; c != coluna + numero_de_colunas; ++c)
00200         {
00201             moveCursorPara(Posicao(l, c));
00202             troco.dados[i++] = SLsmg_char_at();
00203         }
00204 
00205     // Regressar ao cursor inicial:
00206     moveCursorPara(posicao_original_do_cursor);
00207 
00208     return troco;
00209 }
00210 
00211 void Slang::Ecra::cola(Troco const& troco, Posicao const& em)
00212 {
00213     assert(cumpreInvariante());
00214 
00215     verificaRedimensionamento();
00216 
00217     Posicao posicao_original_do_cursor;
00218 
00219     if(cursor_imovel_na_proxima_operacao_de_escrita)
00220         posicao_original_do_cursor = posicaoDoCursor();
00221 
00222     int const linha = em.linha();
00223     int const coluna = em.coluna();
00224     int const numero_de_linhas = troco.dimensao().numeroDeLinhas();
00225     int const numero_de_colunas = troco.dimensao().numeroDeColunas();
00226 
00227     int i = 0;
00228     for(int l = linha; l != linha + numero_de_linhas; ++l)
00229         for(int c = coluna; c != coluna + numero_de_colunas; ++c)
00230         {
00231             moveCursorPara(Posicao(l, c));
00232             char const caractere = troco.dados[i] & 0XFF;
00233             int const objecto = troco.dados[i++] >> 8;
00234             SLsmg_set_color(objecto);
00235             SLsmg_write_char(caractere);
00236         }
00237 
00238     if(cursor_imovel_na_proxima_operacao_de_escrita) {
00239         moveCursorPara(posicao_original_do_cursor);
00240 
00241         cursor_imovel_na_proxima_operacao_de_escrita = false;
00242     }
00243 
00244     // Em vez de regressar ao objecto da próxima escrita, põe-se o fundo:
00245     *this << fundo;
00246 
00247     assert(cumpreInvariante());
00248 }
00249 
00250 void Slang::Ecra::desenha(Caixa const& caixa)
00251 {
00252     assert(cumpreInvariante());
00253 
00254     verificaRedimensionamento();
00255 
00256     Posicao posicao_original_do_cursor;
00257 
00258     if(cursor_imovel_na_proxima_operacao_de_escrita)
00259         posicao_original_do_cursor = posicaoDoCursor();
00260 
00261     SLsmg_draw_box(caixa.origem().linha(), caixa.origem().coluna(), 
00262                    caixa.dimensao().numeroDeLinhas(), 
00263                    caixa.dimensao().numeroDeColunas());
00264 
00265     if(cursor_imovel_na_proxima_operacao_de_escrita)
00266     {
00267         moveCursorPara(posicao_original_do_cursor);
00268 
00269         cursor_imovel_na_proxima_operacao_de_escrita = false;
00270     }
00271 
00272     assert(cumpreInvariante());
00273 }
00274 
00275 void Slang::Ecra::desenhaSegmentoHorizontalCom(int const largura)
00276 {
00277     assert(cumpreInvariante());
00278 
00279     verificaRedimensionamento();
00280 
00281     Posicao posicao_original_do_cursor;
00282 
00283     if(cursor_imovel_na_proxima_operacao_de_escrita)
00284         posicao_original_do_cursor = posicaoDoCursor();
00285 
00286     SLsmg_draw_hline(largura);
00287 
00288     if(cursor_imovel_na_proxima_operacao_de_escrita)
00289     {
00290         moveCursorPara(posicao_original_do_cursor);
00291 
00292         cursor_imovel_na_proxima_operacao_de_escrita = false;
00293     }
00294 
00295     assert(cumpreInvariante());
00296 }
00297 
00298 void Slang::Ecra::desenhaSegmentoVerticalCom(int const altura)
00299 {
00300     assert(cumpreInvariante());
00301 
00302     verificaRedimensionamento();
00303 
00304     Posicao posicao_original_do_cursor;
00305 
00306     if(cursor_imovel_na_proxima_operacao_de_escrita)
00307         posicao_original_do_cursor = posicaoDoCursor();
00308 
00309     SLsmg_draw_vline(altura);
00310 
00311     if(cursor_imovel_na_proxima_operacao_de_escrita)
00312     {
00313         moveCursorPara(posicao_original_do_cursor);
00314 
00315         cursor_imovel_na_proxima_operacao_de_escrita = false;
00316     }
00317 
00318     assert(cumpreInvariante());
00319 }
00320 
00321 Slang::Ecra& Slang::Ecra::operator<<(string const& cadeia_a_escrever)
00322 {
00323     assert(cumpreInvariante());
00324 
00325     verificaRedimensionamento();
00326 
00327     string cadeia = cadeia_a_escrever;
00328 
00329     Posicao posicao_original_do_cursor;
00330     if(cursor_imovel_na_proxima_operacao_de_escrita)
00331         posicao_original_do_cursor = posicaoDoCursor();
00332 
00333     // Usar const_cast (abaixo) é violento, mas a verdade é que p
00334     // SLsmg_write_string deveria declarar parâmetro como char const*...
00335 
00336     if(largura_da_proxima_operacao_de_escrita == 0)
00337         SLsmg_write_string(const_cast<char *>(cadeia.c_str()));
00338     else {
00339         string::size_type espaco_a_usar = 
00340             largura_da_proxima_operacao_de_escrita;
00341 
00342         if(cadeia.size() < espaco_a_usar)
00343             switch(justificacao_actual) {
00344               case ao_centro:
00345                 cadeia = 
00346                     string((espaco_a_usar - cadeia.size() + 1) / 2,
00347                            ' ') + cadeia;
00348                 break;
00349               case a_direita:
00350                 cadeia = 
00351                     string(espaco_a_usar - cadeia.size(), ' ') + 
00352                     cadeia;
00353                 break;
00354               case a_esquerda:
00355                 cadeia += 
00356                     string(espaco_a_usar - cadeia.size(), ' ');
00357                 break;
00358             }
00359         else
00360             switch(justificacao_actual) {
00361               case ao_centro:
00362                 cadeia = cadeia.substr((cadeia.size() - espaco_a_usar) / 2,
00363                                        espaco_a_usar);
00364                 break;
00365               case a_direita:
00366                 cadeia = cadeia.substr(cadeia.size() - espaco_a_usar,
00367                                        espaco_a_usar);
00368                 break;
00369               case a_esquerda:
00370                 cadeia = cadeia.substr(0, espaco_a_usar);
00371                 break;
00372             }
00373             
00374         SLsmg_write_nstring(const_cast<char *>(cadeia.c_str()), 
00375                             espaco_a_usar);
00376 
00377         largura_da_proxima_operacao_de_escrita = 0;
00378     }
00379 
00380     if(cursor_imovel_na_proxima_operacao_de_escrita) {
00381         moveCursorPara(posicao_original_do_cursor);
00382         cursor_imovel_na_proxima_operacao_de_escrita = false;
00383     }
00384 
00385     assert(cumpreInvariante());
00386 
00387     return *this;
00388 }
00389 
00390 Slang::Ecra const& Slang::Ecra::operator>>(Troco& troco) const
00391 {
00392     assert(cumpreInvariante());
00393 
00394     verificaRedimensionamento();
00395 
00396     Posicao const posicao_original_do_cursor = posicaoDoCursor();
00397 
00398     int const linha = posicao_original_do_cursor.linha();
00399     int const coluna = posicao_original_do_cursor.coluna();
00400     int const numero_de_linhas = troco.dimensao().numeroDeLinhas();
00401     int const numero_de_colunas = 
00402         troco.dimensao().numeroDeColunas();
00403 
00404     int i = 0;
00405     for(int l = linha; l != linha + numero_de_linhas; ++l)
00406         for(int c = coluna; c != coluna + numero_de_colunas; ++c) {
00407             moveCursorPara(Posicao(l, c));
00408             troco.dados[i++] = SLsmg_char_at();
00409         }
00410 
00411     moveCursorPara(posicao_original_do_cursor);
00412 
00413     return *this;
00414 }
00415 
00416 void Slang::Ecra::verificaRedimensionamento() const
00417 {
00418     if(tamanho_do_ecra_real_mudou)
00419     {
00420         // A variável tamanho_do_ecra_real_mudou passa a falso.  Ela é
00421         // colocada a true pelo manipulador do sinal SIGWINCH!
00422         tamanho_do_ecra_real_mudou = false;
00423 
00424         // Como o ecrã mudou de tamanho, põe-se a true a variável
00425         // redimensionado_, para que os clientes do ecrã possam
00426         // redesenhar o que for necessário (tipicamente tudo):
00427         redimensionado_ = true;
00428 
00429         // Guarda-se a antiga posição do cursor:
00430         Posicao const posicao_do_cursor = posicaoDoCursor();
00431 
00432         // Obter nova dimensão do ecrã e reinicializar o slang smg:
00433         SLtt_get_screen_size();
00434         SLsmg_reinit_smg();     // a posição do cursor perde-se aqui...
00435 
00436         // Colocar de novo o cursor onde estava:
00437         moveCursorPara(posicao_do_cursor);
00438     }
00439 }
00440 
00441 void Slang::Ecra::moveCursorPara(Posicao const& nova_posicao_do_cursor) const
00442 {
00443     verificaRedimensionamento();
00444 
00445     int linha = nova_posicao_do_cursor.linha();
00446     int coluna = nova_posicao_do_cursor.coluna();
00447 
00448     if(cursor_esta_limitado_ao_ecra_real)
00449     {
00450         if(dimensao().numeroDeLinhas() <= linha) 
00451             linha = dimensao().numeroDeLinhas() - 1;
00452         else if(linha < 0) 
00453             linha = 0;
00454         
00455         if(dimensao().numeroDeColunas() <= coluna) 
00456             coluna = dimensao().numeroDeColunas() - 1;
00457         else if(coluna < 0) 
00458             coluna = 0;
00459     }
00460 
00461     SLsmg_gotorc(linha, coluna);
00462 }
00463 
00464 int Slang::Ecra::reservaObjecto()
00465 {
00466     int numero_do_objecto_reservado = 1;
00467     int ocupacao_minima = ocupacao_dos_objectos[1];
00468 
00469     for(int numero_do_objecto = 2; 
00470         numero_do_objecto != ObjectoCor::numero_de_objectos_cor_no_s_lang; 
00471         ++numero_do_objecto)
00472         if(ocupacao_dos_objectos[numero_do_objecto] < ocupacao_minima) {
00473             ocupacao_minima = ocupacao_dos_objectos[numero_do_objecto];
00474             numero_do_objecto_reservado = numero_do_objecto;
00475         }
00476 
00477     ++ocupacao_dos_objectos[numero_do_objecto_reservado];
00478 
00479     return numero_do_objecto_reservado;
00480 }
00481 
00482 void Slang::Ecra::libertaObjecto(int const numero_do_objecto)
00483 {
00484     assert(1 <= numero_do_objecto and 
00485            numero_do_objecto < ObjectoCor::numero_de_objectos_cor_no_s_lang);
00486     assert(ocupacao_dos_objectos[numero_do_objecto] != 0);
00487 
00488     --ocupacao_dos_objectos[numero_do_objecto];
00489 }
00490 
00491 
00492 bool Slang::Ecra::ja_existe_instancia = false;
00493 
00494 bool volatile Slang::Ecra::tamanho_do_ecra_real_mudou = false;
00495 
00496 char* Slang::Ecra::nome_de_cor_do_s_lang[numero_de_cores] = {
00497     "black",
00498     "gray",
00499     "red",
00500     "brightred",
00501     "green",
00502     "brightgreen",
00503     "brown",
00504     "yellow",
00505     "blue",
00506     "brightblue",
00507     "magenta",
00508     "brightmagenta",
00509     "cyan",
00510     "brightcyan",
00511     "lightgray",
00512     "white"
00513 };
00514 
00515 Slang::Ecra Slang::ecra;
00516 
00517 string const Slang::nomes_das_cores[numero_de_cores] = {
00518     "preto",
00519     "cinza",
00520     "vermelho",
00521     "vermelho-brilhante",
00522     "verde",
00523     "verde-brilhante",
00524     "castanho",
00525     "amarelo",
00526     "azul",
00527     "azul-brilhante",
00528     "magenta",
00529     "magenta-brilhante",
00530     "ciano",
00531     "ciano-brilhante",
00532     "cinzento-claro",
00533     "branco"
00534 };
00535 
00536 
00537 #ifdef TESTE
00538 
00539 #include <fstream>
00540 
00541 using namespace Slang;
00542 
00543 int main()
00544 {
00545     Posicao p;
00546 
00547     assert(p == Posicao());
00548     assert(p == Posicao(0, 0));
00549 
00550     p.mudaLinhaPara(10);
00551     p.mudaColunaPara(20);
00552 
00553     assert(p == Posicao(10, 20));
00554     assert(p.linha() == 10);
00555     assert(p.coluna() == 20);
00556 
00557     ofstream saida("ecra.lixo");
00558 
00559     p.guardaEm(saida);
00560 
00561     saida.close();
00562 
00563     ifstream entrada("ecra.lixo");
00564 
00565     Posicao q(entrada);
00566 
00567     assert(p == q);
00568 
00569     entrada.seekg(0);
00570 
00571     p = Posicao(0, 0);
00572 
00573     assert(p == Posicao(0, 0));
00574 
00575     p.carregaDe(entrada);
00576 
00577     entrada.close();
00578 
00579     assert(p == q);
00580 
00581     p += Dimensao(-20, -10);
00582 
00583     assert(p == Posicao(-10, 10));
00584 
00585     p -= Dimensao(-20, -10);
00586 
00587     assert(p == q);
00588 
00589     assert(p + Dimensao(-20, -10) == Posicao(-10, 10));
00590 
00591     assert(p - Dimensao(20, 10) == Posicao(-10, 10));
00592 
00593     assert(Dimensao(-20, -10) + p == Posicao(-10, 10));
00594     
00595     assert(Dimensao(20, 10) - p == Posicao(10, -10));
00596 
00597     assert(p - Posicao(0, 0) == Dimensao(10, 20));
00598 
00599     assert(Posicao(0, 0) - p == Dimensao(-10, -20));
00600 
00601     assert(-p == Posicao(-10, -20));
00602 
00603 
00604     Dimensao d(p);
00605 
00606     assert(d == Dimensao(10, 20));
00607 
00608     assert(d.numeroDeLinhas() == 10);
00609 
00610     assert(d.numeroDeColunas() == 20);
00611 
00612     assert(d.eCanonica());
00613 
00614     d = -d;
00615 
00616     assert(d == Dimensao(-10, -20));
00617 
00618     assert(not d.eCanonica());
00619 
00620     d.mudaNumeroDeLinhasPara(0);
00621 
00622     d.mudaNumeroDeColunasPara(0);
00623 
00624     assert(d == Dimensao(0, 0));
00625 
00626     d = Dimensao(p);
00627 
00628     assert(d == Dimensao(10, 20));
00629 
00630     saida.open("ecra.lixo");
00631 
00632     d.guardaEm(saida);
00633 
00634     saida.close();
00635 
00636     entrada.open("ecra.lixo");
00637 
00638     Dimensao e(entrada);
00639 
00640     assert(d == e);
00641 
00642     entrada.seekg(0);
00643 
00644     d = Dimensao(0, 0);
00645 
00646     assert(d == Dimensao(0, 0));
00647 
00648     d.carregaDe(entrada);
00649 
00650     entrada.close();
00651 
00652     assert(d == e);
00653 
00654     d += Dimensao(-20, -10);
00655 
00656     assert(d == Dimensao(-10, 10));
00657 
00658     d -= Dimensao(-20, -10);
00659 
00660     assert(d == e);
00661 
00662     assert(d + Dimensao(-20, -10) == Dimensao(-10, 10));
00663 
00664     assert(d - Dimensao(20, 10) == Dimensao(-10, 10));
00665 
00666 
00667     Caixa c1(Posicao(10, 20), Dimensao(3, 6));
00668     Caixa c2(Posicao(10, 20), Posicao(12, 25));
00669 
00670     assert(not c1.eVazia());
00671 
00672     assert(c1.eCanonica());
00673     
00674     assert(c1 == c2);
00675 
00676     assert(c1.origem() == Posicao(10, 20));
00677     assert(c1.extremo() == Posicao(12, 25));
00678     assert(c1.dimensao() == Dimensao(3, 6));
00679 
00680     c1.mudaDimensaoPara(Dimensao(0, 0));
00681 
00682     assert(c1.eVazia());
00683 
00684     assert(c1.eCanonica());
00685 
00686     c1.mudaDimensaoPara(Dimensao(-6, -8));
00687 
00688     assert(not c1.eVazia());
00689 
00690     assert(not c1.eCanonica());
00691 
00692     assert(c1.extremo() == Posicao(3, 11));
00693     assert(c1.dimensao() == Dimensao(-6, -8));
00694     
00695     c1 += Dimensao(7, 9);
00696 
00697     assert(c1.dimensao() == Dimensao(-6, -8));
00698     assert(c1.origem() == Posicao(17, 29));
00699 
00700     assert((c1 + Dimensao(-7, -9)).origem() == Posicao(10, 20));
00701     assert((c1 - Dimensao(7, 9)).origem() == Posicao(10, 20));
00702 
00703     assert(c1 + c2 == Caixa(Posicao(10, 20), Posicao(12, 25)));
00704     assert(c1 * c2 == Caixa(Posicao(17, 29), Posicao(10, 20)));
00705 
00706     // Não se testam classes com interface gráfica...
00707 }
00708 
00709 #endif // TESTE

Gerado em Tue Dec 3 15:19:34 2002 para Pacotes por doxygen1.3-rc1