Página principal   Módulos   Lista de namespaces   Hierarquia de classes   Lista de componentes   Lista de ficheiros   Membros do namespace   Componentes   Declarações   Paginas relacionadas  

ecra.C

Ir para a documentação deste ficheiro.
00001 #include <Slang/ecra.H>
00002 
00003 #include <Slang/util.H>
00004 
00005 
00006 // Definição de métodos de Posicao:
00007 
00008 void Slang::Posicao::carrega(std::istream& entrada) 
00009 {
00010     int l, c;                   // Assim garante-se bom comportamento em caso
00011                                 // de erro.
00012     if(!(entrada >> l >> Slang::il >> c >> Slang::il))
00013         throw ErroAoCarregar("Posicao");
00014     linha_ = l;
00015     coluna_ = c;
00016 }
00017 
00018 void Slang::Posicao::guarda(std::ostream& saida) const
00019 {
00020     if(!(saida << linha_ << endl << coluna_ << endl))
00021         throw ErroAoGuardar("Posicao");
00022 }
00023 
00024 
00025 // Definição de métodos de Dimensao:
00026 
00027 void Slang::Dimensao::carrega(std::istream& entrada) 
00028 {
00029     int l, c;                   // Assim garante-se bom comportamento em caso
00030                                 // de erro.
00031     if(!(entrada >> l >> Slang::il >> c >> Slang::il))
00032         throw ErroAoCarregar("Dimensao");
00033     linhas_ = l;
00034     colunas_ = c;
00035 }
00036 
00037 void Slang::Dimensao::guarda(std::ostream& saida) const
00038 {
00039     if(!(saida << linhas_ << endl << colunas_ << endl))
00040         throw ErroAoGuardar("Dimensao");
00041 }
00042 
00043 
00044 // Definição de métodos de Caixa:
00045 
00046 void Slang::Caixa::carrega(std::istream& entrada) 
00047 {
00048     /* Para garantir bom comportamento face a excepções tem de se complicar um 
00049        pouco o código, que não pode ser simplesmente:
00050 
00051         origem_.carrega(entrada);
00052         dimensao_.carrega(entrada);
00053 
00054        Cada um dos carregas invocado comporta-se bem, só alterando a instância 
00055        implícita se tiver sucesso total.  Mas acontece que o carregamento de
00056        uma caixa pode falhar por falhar o carregamento da dimensão, e nesse
00057        caso a dimensão não é alterada mas a origem já o foi!
00058     */
00059     Posicao origem(entrada);
00060     dimensao_.carrega(entrada);
00061     origem_ = origem;           // esta atribuição nunca falha!
00062     
00063 }
00064 
00065 void Slang::Caixa::guarda(std::ostream& saida) const
00066 {
00067     origem_.guarda(saida);
00068     dimensao_.guarda(saida);
00069 }
00070 
00071 
00072 // Operadores de leitura e escrita de cores!
00073 std::ostream& Slang::operator << (std::ostream& saida, Slang::Cor cor) 
00074 {
00075     return saida << Slang::nomes_das_cores[cor];
00076 }
00077 
00078 std::istream& Slang::operator >> (std::istream& entrada, Slang::Cor& cor) 
00079 {
00080     string nome;
00081     if(entrada >> nome) {
00082         for(int c = Slang::primeira_cor; c != Slang::numero_de_cores; ++c)
00083             if(Slang::nomes_das_cores[c] == nome) {
00084                 cor = Slang::Cor(c);
00085                 return entrada;
00086             }
00087         entrada.clear(ios::badbit); // devia ser ios_base::badbit
00088     }
00089     return entrada;
00090 }
00091 
00092 
00093 // Definição de métodos de classe de Ecra:
00094 
00095 Slang::Ecra::Ecra(Cor texto, Cor fundo, bool limita_cursor)
00096     : limita_cursor(limita_cursor), redimensionado_(true),
00097       para_no_proximo(false), justificacao(a_esquerda), largura_do_proximo(0), 
00098       ocupacao_objecto(256) {
00099 
00100     assert(!existe_instancia);
00101 
00102     existe_instancia = true;
00103     // Inicializações do slang:
00104     SLtt_get_terminfo();
00105     if(SLsmg_init_smg() == -1) {
00106         // Que fazer?
00107     }
00108     // Inicialização do manipulador de mudanças no ecrã:
00109     SLsignal(SIGWINCH, manipuladorTamanhoMudou);
00110     atributos(texto, fundo);
00111 }
00112 
00113 Slang::Ecra::Troco Slang::Ecra::copia(Caixa const& caixa) const 
00114 {
00115     verificaTamanho();
00116 
00117     // Guardar cursor inicial:
00118     Posicao const posicao_original_do_cursor = cursor();
00119 
00120     int const linha = caixa.origem().linha(); 
00121     int const coluna = caixa.origem().coluna();
00122     int const linhas = caixa.dimensao().linhas();
00123     int const colunas = caixa.dimensao().colunas();
00124 
00125     Troco troco(caixa.dimensao());
00126     int i = 0;
00127     for(int l = linha; l != linha + linhas; ++l)
00128         for(int c = coluna; c != coluna + colunas; ++c)
00129         {
00130             cursor(Posicao(l, c));
00131             troco.dados[i++] = SLsmg_char_at();
00132         }
00133 
00134     // Regressar ao cursor inicial:
00135     cursor(posicao_original_do_cursor);
00136 
00137     return troco;
00138 }
00139 
00140 void Slang::Ecra::cola(Troco const& troco, Posicao const& posicao)
00141 {
00142     verificaTamanho();
00143 
00144     // Guardar cursor inicial:
00145     Posicao posicao_original_do_cursor;
00146     if(para_no_proximo)
00147         posicao_original_do_cursor = cursor();
00148 
00149     // Afazer: devia-se guardar também o objecto da próxima escrita...
00150 
00151     int const linha = posicao.linha();
00152     int const coluna = posicao.coluna();
00153     int const linhas = troco.dimensao().linhas();
00154     int const colunas = troco.dimensao().colunas();
00155 
00156     int i = 0;
00157     for(int l = linha; l != linha + linhas; ++l)
00158         for(int c = coluna; c != coluna + colunas; ++c)
00159         {
00160             cursor(Posicao(l, c));
00161             char const caractere = troco.dados[i] & 0XFF;
00162             int const objecto = troco.dados[i++] >> 8;
00163             SLsmg_set_color(objecto);
00164             SLsmg_write_char(caractere);
00165         }
00166 
00167     // Regressar ao cursor inicial:
00168     if(para_no_proximo) {
00169         cursor(posicao_original_do_cursor);
00170         para_no_proximo = false;
00171     }
00172 
00173     // Em vez de regressar ao objecto da próxima escrita (Afazer:
00174     // melhorar no futuro), põe-se o fundo:
00175     *this << fundo;
00176 }
00177 
00178 Slang::Ecra& Slang::Ecra::operator << (string s)
00179 {
00180     verificaTamanho();
00181 
00182     Posicao posicao_original_do_cursor;
00183     if(para_no_proximo)
00184         posicao_original_do_cursor = cursor();
00185 
00186     if(largura_do_proximo == 0)
00187         SLsmg_write_string(const_cast<char *>(s.c_str()));
00188     else {
00189         if(s.size() < string::size_type(largura_do_proximo))
00190             switch(justificacao) {
00191               case ao_centro:
00192                 s = string((largura_do_proximo - s.size() + 1) / 2, ' ') + s;
00193                 break;
00194               case a_direita:
00195                 s = string(largura_do_proximo - s.size(), ' ') + s;
00196                 break;
00197               case a_esquerda:
00198                 s += string(largura_do_proximo - s.size(), ' ');
00199                 break;
00200             }
00201         SLsmg_write_nstring(const_cast<char *>(s.c_str()), 
00202                             largura_do_proximo);
00203         largura_do_proximo = 0;
00204     }
00205     // Usar const_cast é violento, mas a verdade é que p
00206     // SLsmg_write_string deveria declarar parâmetro como char const*
00207 
00208     if(para_no_proximo) {
00209         cursor(posicao_original_do_cursor);
00210         para_no_proximo = false;
00211     }
00212 
00213     return *this;
00214 }
00215 
00216 Slang::Ecra& Slang::Ecra::operator << (Simbolo simbolo)
00217 {
00218     char c = simbolo;
00219     SLsmg_set_char_set(1);
00220     *this << c;
00221     SLsmg_set_char_set(0);
00222 
00223     return *this;
00224 }
00225 
00226 Slang::Ecra const& Slang::Ecra::operator >> (Troco& troco) const
00227 {
00228     verificaTamanho();
00229 
00230     Posicao const posicao_original_do_cursor = cursor();
00231 
00232     int const linha = posicao_original_do_cursor.linha();
00233     int const coluna = posicao_original_do_cursor.coluna();
00234     int const linhas = troco.dimensao().linhas();
00235     int const colunas = troco.dimensao().colunas();
00236 
00237     int i = 0;
00238     for(int l = linha; l != linha + linhas; ++l)
00239         for(int c = coluna; c != coluna + colunas; ++c) {
00240             cursor(Posicao(l, c));
00241             troco.dados[i++] = SLsmg_char_at();
00242         }
00243 
00244     cursor(posicao_original_do_cursor);
00245 
00246     return *this;
00247 }
00248 
00249 void Slang::Ecra::verificaTamanho() const
00250 {
00251     if(tamanho_mudou)
00252     {
00253         // A variável tamanho_mudou passa a falso.  Ela é colocada a
00254         // true pelo manipulador do sinal SIGWINCH!
00255         tamanho_mudou = false;
00256 
00257         // Como o ecrã mudou de tamanho, põe-se a true a variável
00258         // redimensionado_, para que os clientes do ecrã possam
00259         // redesenhar o que for necessário (tipicamente tudo):
00260         redimensionado_ = true;
00261 
00262         // Guarda-se a antiga posição do cursor:
00263         Posicao const posicao_do_cursor = cursor();
00264 
00265         // Obter nova dimensão do ecrã e reinicializar o slang smg:
00266         SLtt_get_screen_size();
00267         SLsmg_reinit_smg();     // a posição do cursor perde-se aqui...
00268 
00269         // Colocar de novo o cursor onde estava:
00270         cursor(posicao_do_cursor);
00271     }
00272 }
00273 
00274 int Slang::Ecra::reservaObjecto()
00275 {
00276     int objecto = 1;
00277     int ocupacao_minima = ocupacao_objecto[1];
00278     for(int o = 2; o != 256; ++o)
00279         if(ocupacao_objecto[o] < ocupacao_minima) {
00280             ocupacao_minima = ocupacao_objecto[o];
00281             objecto = o;
00282         }
00283     ++ocupacao_objecto[objecto];
00284     return objecto;
00285 }
00286 
00287 
00288 // Definição de métodos de classe de Ecra:
00289 
00290 void Slang::Ecra::manipuladorTamanhoMudou(int sinal)
00291 {
00292     Slang::Ecra::tamanho_mudou = true;
00293     SLsignal(SIGWINCH, manipuladorTamanhoMudou);
00294 }
00295 
00296 
00297 // Definição de variáveis de classe de Ecra:
00298 
00299 bool Slang::Ecra::existe_instancia = false;
00300 
00301 bool volatile Slang::Ecra::tamanho_mudou = false;
00302 
00303 char* Slang::Ecra::nome_de_cor[numero_de_cores] = {
00304     "black",
00305     "gray",
00306     "red",
00307     "brightred",
00308     "green",
00309     "brightgreen",
00310     "brown",
00311     "yellow",
00312     "blue",
00313     "brightblue",
00314     "magenta",
00315     "brightmagenta",
00316     "cyan",
00317     "brightcyan",
00318     "lightgray",
00319     "white"
00320 };
00321 
00322 
00323 // Definição de variáveis globais:
00324 
00325 string const Slang::nomes_das_cores[numero_de_cores] = {
00326     "preto",
00327     "cinza",
00328     "vermelho",
00329     "vermelho-brilhante",
00330     "verde",
00331     "verde-brilhante",
00332     "castanho",
00333     "amarelo",
00334     "azul",
00335     "azul-brilhante",
00336     "magenta",
00337     "magenta-brilhante",
00338     "ciano",
00339     "ciano-brilhante",
00340     "cinzento-claro",
00341     "branco"
00342 };
00343 
00344 Slang::Ecra Slang::ecra;

Gerado em Mon May 14 17:22:13 2001 para Slang++ por doxygen1.2.6 escrito por Dimitri van Heesch, © 1997-2001