00001 #include <cassert>
00002 #include <cstdio>
00003
00004 extern "C" {
00005 #include <slang/slang.h>
00006 #include <signal.h>
00007 }
00008
00009
00010
00011
00012 inline Slang::Posicao::Posicao(int linha, int coluna)
00013 : linha_(linha), coluna_(coluna) {
00014 }
00015
00016 inline Slang::Posicao::Posicao(istream& entrada) {
00017 carrega(entrada);
00018 }
00019
00020
00021 inline int Slang::Posicao::linha() const {
00022 return linha_;
00023 }
00024
00025 inline int Slang::Posicao::coluna() const {
00026 return coluna_;
00027 }
00028
00029
00030 inline void Slang::Posicao::linha(int linha) {
00031 linha_ = linha;
00032 }
00033
00034 inline void Slang::Posicao::coluna(int coluna) {
00035 coluna_ = coluna;
00036 }
00037
00038 inline Slang::Posicao&
00039 Slang::Posicao::operator += (Posicao const& c) {
00040 linha_ += c.linha_;
00041 coluna_ += c.coluna_;
00042 return *this;
00043 }
00044
00045 inline Slang::Posicao&
00046 Slang::Posicao::operator -= (Posicao const& c) {
00047 linha_ -= c.linha_;
00048 coluna_ -= c.coluna_;
00049 return *this;
00050 }
00051
00052 inline Slang::Posicao&
00053 Slang::Posicao::operator += (Dimensao const& c) {
00054 linha_ += c.linhas();
00055 coluna_ += c.colunas();
00056 return *this;
00057 }
00058
00059 inline Slang::Posicao&
00060 Slang::Posicao::operator -= (Dimensao const& c) {
00061 linha_ -= c.linhas();
00062 coluna_ -= c.colunas();
00063 return *this;
00064 }
00065
00066
00067
00068 inline Slang::Posicao
00069 Slang::operator + (Slang::Posicao a, Slang::Posicao const& b) {
00070 return a += b;
00071 }
00072
00073 inline Slang::Posicao
00074 Slang::operator - (Slang::Posicao a, Slang::Posicao const& b) {
00075 return a -= b;
00076 }
00077
00078 inline Slang::Posicao
00079 Slang::operator + (Slang::Posicao a, Slang::Dimensao const& b) {
00080 return a += b;
00081 }
00082
00083 inline Slang::Posicao
00084 Slang::operator - (Slang::Posicao a, Slang::Dimensao const& b) {
00085 return a -= b;
00086 }
00087
00088 inline Slang::Posicao
00089 Slang::operator - (Slang::Posicao const& b) {
00090 return Posicao(-b.linha(), -b.coluna());
00091 }
00092
00093 inline bool
00094 Slang::operator == (Slang::Posicao const& a, Slang::Posicao const& b) {
00095 return a.linha() == b.linha() && a.coluna() == b.coluna();
00096 }
00097
00098
00099
00100
00101 inline Slang::Dimensao::Dimensao(int l, int c) {
00102 linhas(l);
00103 colunas(c);
00104 }
00105
00106 inline Slang::Dimensao::Dimensao(Posicao const& c) {
00107 linhas(c.linha());
00108 colunas(c.coluna());
00109 }
00110
00111 inline Slang::Dimensao::Dimensao(istream& entrada) {
00112 carrega(entrada);
00113 }
00114
00115
00116 inline int Slang::Dimensao::linhas() const {
00117 return linhas_;
00118 }
00119
00120 inline int Slang::Dimensao::colunas() const {
00121 return colunas_;
00122 }
00123
00124
00125 inline void Slang::Dimensao::linhas(int linhas) {
00126 linhas_ = linhas < 0 ? 0 : linhas;
00127 }
00128
00129 inline void Slang::Dimensao::colunas(int colunas) {
00130 colunas_ = colunas < 0 ? 0 : colunas;
00131 }
00132
00133
00134 inline Slang::Dimensao& Slang::Dimensao::operator += (Dimensao const& c) {
00135 linhas(linhas() + c.linhas());
00136 colunas(colunas() + c.colunas());
00137 return *this;
00138 }
00139
00140 inline Slang::Dimensao& Slang::Dimensao::operator -= (Dimensao const& c) {
00141 linhas(linhas() - c.linhas());
00142 colunas(colunas() - c.colunas());
00143 return *this;
00144 }
00145
00146
00147 inline Slang::Dimensao Slang::operator + (Dimensao a, Dimensao const& b) {
00148 return a += b;
00149 }
00150
00151 inline Slang::Dimensao Slang::operator - (Dimensao a, Dimensao const& b) {
00152 return a -= b;
00153 }
00154
00155 inline bool
00156 Slang::operator == (Slang::Dimensao const& a, Slang::Dimensao const& b) {
00157 return a.linhas() == b.linhas() && a.colunas() == b.colunas();
00158 }
00159
00160
00161
00162
00163
00164 inline Slang::Caixa::Caixa(Posicao const& origem, Dimensao const& dimensao)
00165 : origem_(origem), dimensao_(dimensao) {
00166 }
00167
00168 inline Slang::Caixa::Caixa(Posicao const& a, Posicao const& b)
00169 : origem_(min(a.linha(), b.linha()), min(a.coluna(), b.coluna())),
00170 dimensao_(abs(a.linha() - b.linha()) + 1,
00171 abs(a.coluna() - b.coluna()) + 1) {
00172 }
00173
00174 inline Slang::Caixa::Caixa(istream& entrada)
00175 : origem_(entrada), dimensao_(entrada) {
00176 }
00177
00178
00179
00180 inline Slang::Posicao Slang::Caixa::origem() const {
00181 return origem_;
00182 }
00183
00184 inline Slang::Posicao Slang::Caixa::destino() const {
00185 return origem_ + dimensao_ - Posicao(1, 1);
00186 }
00187
00188 inline Slang::Dimensao Slang::Caixa::dimensao() const {
00189 return dimensao_;
00190 }
00191
00192 inline bool Slang::Caixa::vazia() const {
00193 return dimensao().linhas() == 0 || dimensao().colunas() == 0;
00194 }
00195
00196 inline bool Slang::Caixa::contem(Posicao const& c) const {
00197 int const linha = origem_.linha();
00198 int const coluna = origem_.coluna();
00199 int const linha_final = linha + dimensao_.linhas();
00200 int const coluna_final = coluna + dimensao_.colunas();
00201 return c.linha() >= linha && c.linha() < linha_final &&
00202 c.coluna() >= coluna && c.coluna() < coluna_final;
00203 }
00204
00205 inline bool Slang::Caixa::bordaContem(Posicao const& c) const {
00206 int const primeira_linha = origem().linha();
00207 int const primeira_coluna = origem().coluna();
00208 int const ultima_linha = destino().linha();
00209 int const ultima_coluna = destino().coluna();
00210 return ((c.linha() >= primeira_linha && c.linha() <= ultima_linha &&
00211 (c.coluna() == primeira_coluna || c.coluna() == ultima_coluna)) ||
00212 (c.coluna() >= primeira_coluna && c.coluna() <= ultima_coluna &&
00213 (c.linha() == primeira_linha || c.linha() == ultima_linha)));
00214 }
00215
00216
00217 inline void Slang::Caixa::origem(Posicao const & origem) {
00218 origem_ = origem;
00219 }
00220
00221 inline void Slang::Caixa::destino(Posicao const& destino) {
00222 *this = Caixa(origem(), destino);
00223 }
00224
00225 inline void Slang::Caixa::dimensao(Dimensao const& dimensao) {
00226 dimensao_ = dimensao;
00227 }
00228
00229
00230 inline Slang::Caixa& Slang::Caixa::operator += (Slang::Posicao const& c) {
00231 origem(origem() + c);
00232 return *this;
00233 }
00234
00235 inline Slang::Caixa& Slang::Caixa::operator += (Slang::Caixa const& c) {
00236 if(vazia()) return *this = c;
00237 if(c.vazia()) return *this;
00238 int const linha = min(origem_.linha(), c.origem_.linha());
00239 int const coluna = min(origem_.coluna(), c.origem_.coluna());
00240 int const linha_final = max(origem_.linha() + dimensao_.linhas(),
00241 c.origem_.linha() + c.dimensao_.linhas());
00242 int const coluna_final = max(origem_.coluna() + dimensao_.colunas(),
00243 c.origem_.coluna() + c.dimensao_.colunas());
00244 origem_.linha(linha);
00245 origem_.coluna(coluna);
00246 dimensao_.linhas(linha_final - linha);
00247 dimensao_.colunas(coluna_final - coluna);
00248
00249 return *this;
00250 }
00251
00252 inline Slang::Caixa& Slang::Caixa::operator *= (Slang::Caixa const& c) {
00253 if(vazia() || c.vazia())
00254 return *this = caixa_vazia;
00255 int const linha = max(origem_.linha(), c.origem_.linha());
00256 int const coluna = max(origem_.coluna(), c.origem_.coluna());
00257 int const linha_final = min(origem_.linha() + dimensao_.linhas(),
00258 c.origem_.linha() + c.dimensao_.linhas());
00259 int const coluna_final = min(origem_.coluna() + dimensao_.colunas(),
00260 c.origem_.coluna() + c.dimensao_.colunas());
00261 if(linha_final < linha || coluna_final < coluna)
00262 return *this = caixa_vazia;
00263
00264 origem_.linha(linha);
00265 origem_.coluna(coluna);
00266 dimensao_.linhas(linha_final - linha);
00267 dimensao_.colunas(coluna_final - coluna);
00268
00269 return *this;
00270 }
00271
00272
00273 inline Slang::Caixa Slang::operator + (Slang::Caixa caixa,
00274 Slang::Posicao const& c) {
00275 return caixa += c;
00276 }
00277
00278 inline Slang::Caixa Slang::operator + (Slang::Posicao const& c,
00279 Slang::Caixa caixa) {
00280 return caixa += c;
00281 }
00282
00283 inline Slang::Caixa Slang::operator + (Slang::Caixa a, Slang::Caixa const& b) {
00284 return a += b;
00285 }
00286
00287 inline Slang::Caixa Slang::operator * (Slang::Caixa a, Slang::Caixa const& b) {
00288 return a *= b;
00289 }
00290
00291
00292
00293
00294 inline Slang::Ecra::~Ecra() {
00295
00296 SLsmg_reset_smg();
00297 }
00298
00299 inline void Slang::Ecra::atributos(Cor texto, Cor fundo, int objecto) {
00300 SLtt_set_color(objecto, 0, nome_de_cor[texto], nome_de_cor[fundo]);
00301 }
00302
00303 inline void Slang::Ecra::atributos(Cor texto, Cor fundo) {
00304 SLtt_set_color(0, 0, nome_de_cor[texto], nome_de_cor[fundo]);
00305 }
00306
00307 inline Slang::Dimensao Slang::Ecra::dimensao() const {
00308 verificaTamanho();
00309 return Dimensao(SLtt_Screen_Rows, SLtt_Screen_Cols);
00310 }
00311
00312 inline Slang::Posicao Slang::Ecra::cursor() const {
00313 return Posicao(SLsmg_get_row(), SLsmg_get_column());
00314 }
00315
00316 inline bool Slang::Ecra::redimensionado() const {
00317 verificaTamanho();
00318 if(redimensionado_) {
00319 redimensionado_ = false;
00320 return true;
00321 }
00322 return false;
00323 }
00324
00325 inline Slang::Ecra::Troco Slang::Ecra::copia(Dimensao const& dimensao) const {
00326 return copia(Caixa(cursor(), dimensao));
00327 }
00328
00329 inline Slang::Ecra::Troco Slang::Ecra::copia() const {
00330 return copia(Caixa(Posicao(0, 0), dimensao()));
00331 }
00332
00333 inline void Slang::Ecra::cursor(Posicao const& posicao) {
00334 verificaTamanho();
00335 int linha = posicao.linha();
00336 int coluna = posicao.coluna();
00337 if(limita_cursor) {
00338 if(linha >= dimensao().linhas()) linha = dimensao().linhas() - 1;
00339 else if(linha < 0) linha = 0;
00340
00341 if(coluna >= dimensao().colunas()) coluna = dimensao().colunas() - 1;
00342 else if(coluna < 0) coluna = 0;
00343 }
00344 SLsmg_gotorc(linha, coluna);
00345 }
00346
00347 inline void Slang::Ecra::cursor(Posicao const& posicao) const {
00348 verificaTamanho();
00349 int linha = posicao.linha();
00350 int coluna = posicao.coluna();
00351 if(limita_cursor) {
00352 if(linha >= dimensao().linhas()) linha = dimensao().linhas() - 1;
00353 else if(linha < 0) linha = 0;
00354
00355 if(coluna >= dimensao().colunas()) coluna = dimensao().colunas() - 1;
00356 else if(coluna < 0) coluna = 0;
00357 }
00358 SLsmg_gotorc(linha, coluna);
00359 }
00360
00361 inline void Slang::Ecra::cima() {
00362 cursor(Posicao(cursor().linha() - 1, cursor().coluna()));
00363 }
00364
00365 inline void Slang::Ecra::baixo() {
00366 cursor(Posicao(cursor().linha() + 1, cursor().coluna()));
00367 }
00368
00369 inline void Slang::Ecra::esquerda() {
00370 cursor(Posicao(cursor().linha(), cursor().coluna() - 1));
00371 }
00372
00373 inline void Slang::Ecra::direita() {
00374 cursor(Posicao(cursor().linha(), cursor().coluna() + 1));
00375 }
00376
00377 inline void Slang::Ecra::desloca(Slang::Tecla const& tecla) {
00378 switch(tecla) {
00379 case Tecla::cima:
00380 cima();
00381 break;
00382 case Tecla::baixo:
00383 baixo();
00384 break;
00385 case Tecla::esquerda:
00386 esquerda();
00387 break;
00388 case Tecla::direita:
00389 direita();
00390 break;
00391 default:
00392 break;
00393 }
00394 }
00395
00396 inline void Slang::Ecra::campainha() const {
00397 verificaTamanho();
00398 SLtt_beep();
00399 }
00400
00401 inline void Slang::Ecra::apagaFimDaLinha() {
00402 verificaTamanho();
00403 SLsmg_erase_eol();
00404 }
00405
00406 inline void Slang::Ecra::apagaFimDoEcra() {
00407 verificaTamanho();
00408 SLsmg_erase_eos();
00409 }
00410
00411 inline void Slang::Ecra::apaga() {
00412 verificaTamanho();
00413 SLsmg_cls();
00414 }
00415
00416 inline void Slang::Ecra::refrescaTudo() const {
00417 verificaTamanho();
00418
00419 SLsmg_touch_lines(0, dimensao().linhas());
00420 refresca();
00421 }
00422
00423 inline void Slang::Ecra::refresca() const {
00424 verificaTamanho();
00425 SLsmg_refresh();
00426 }
00427
00428 inline void Slang::Ecra::desenhaCaixa(Caixa const& caixa)
00429 {
00430 verificaTamanho();
00431
00432 Posicao posicao_original_do_cursor;
00433 if(para_no_proximo)
00434 posicao_original_do_cursor = cursor();
00435
00436 SLsmg_draw_box(caixa.origem().linha(), caixa.origem().coluna(),
00437 caixa.dimensao().linhas(), caixa.dimensao().colunas());
00438
00439
00440 if(para_no_proximo) {
00441 cursor(posicao_original_do_cursor);
00442 para_no_proximo = false;
00443 }
00444 }
00445
00446 inline Slang::Ecra& Slang::Ecra::operator << (char c) {
00447 string s;
00448 s += c;
00449 return *this << s;
00450 }
00451
00452 inline Slang::Ecra& Slang::Ecra::operator << (int i) {
00453
00454 char mal_feito[30];
00455 std::sprintf(mal_feito, "%d", i);
00456 return *this << mal_feito;
00457 }
00458
00459 inline Slang::Ecra& Slang::Ecra::operator << (Caixa const& caixa) {
00460 desenhaCaixa(caixa);
00461 return *this;
00462 }
00463
00464 inline Slang::Ecra& Slang::Ecra::operator << (Troco const& troco) {
00465 cola(troco, cursor());
00466 return *this;
00467 }
00468
00469 inline Slang::Ecra& Slang::Ecra::operator << (Posicao const& posicao) {
00470 verificaTamanho();
00471 cursor(posicao);
00472 return *this;
00473 }
00474
00475 inline Slang::Ecra& Slang::Ecra::operator << (ObjectoCor const& o) {
00476 verificaTamanho();
00477 SLsmg_set_color(o.objecto);
00478 return *this;
00479 }
00480
00481 inline Slang::Ecra& Slang::Ecra::operator << (Fundo const&) {
00482 verificaTamanho();
00483 SLsmg_set_color(0);
00484 return *this;
00485 }
00486
00487 inline Slang::Ecra& Slang::Ecra::operator << (Parado const&) {
00488 verificaTamanho();
00489 para_no_proximo = true;
00490 return *this;
00491 }
00492
00493 inline Slang::Ecra& Slang::Ecra::operator << (Justificacao const& j) {
00494 verificaTamanho();
00495 justificacao = j;
00496 return *this;
00497 }
00498
00499 inline Slang::Ecra& Slang::Ecra::operator << (Largura const& l) {
00500 verificaTamanho();
00501 largura_do_proximo = l.largura;
00502 return *this;
00503 }
00504
00505 inline Slang::Ecra& Slang::Ecra::operator << (Linha const& linha) {
00506 verificaTamanho();
00507 if(linha.horizontal)
00508 SLsmg_draw_hline(linha.dimensao);
00509 else
00510 SLsmg_draw_vline(linha.dimensao);
00511 return *this;
00512 }
00513
00514 inline Slang::Ecra& Slang::Ecra::operator << (Refresca const&) {
00515 refresca();
00516 return *this;
00517 }
00518
00519 inline Slang::Ecra& Slang::Ecra::operator << (RefrescaTudo const&) {
00520 refrescaTudo();
00521 return *this;
00522 }
00523
00524 inline Slang::Ecra& Slang::Ecra::operator << (Apaga const&) {
00525 apaga();
00526 return *this;
00527 }
00528
00529 inline Slang::Ecra& Slang::Ecra::operator << (ApagaFimDaLinha const&) {
00530 apagaFimDaLinha();
00531 return *this;
00532 }
00533
00534 inline Slang::Ecra& Slang::Ecra::operator << (ApagaFimDoEcra const&) {
00535 apagaFimDoEcra();
00536 return *this;
00537 }
00538
00539 inline Slang::Ecra& Slang::Ecra::operator << (Campainha const&) {
00540 campainha();
00541 return *this;
00542 }
00543
00544 inline void Slang::Ecra::libertaObjecto(int objecto) {
00545 assert(ocupacao_objecto[objecto] != 0);
00546 --ocupacao_objecto[objecto];
00547 }
00548
00549
00550
00551 inline Slang::Ecra::ObjectoCor::ObjectoCor(Cor texto, Cor fundo)
00552 : texto_(texto), fundo_(fundo) {
00553 objecto = ecra.reservaObjecto();
00554 ecra.atributos(texto, fundo, objecto);
00555 }
00556
00557 inline Slang::Ecra::ObjectoCor::~ObjectoCor() {
00558 ecra.libertaObjecto(objecto);
00559 }
00560
00561 inline Slang::Cor Slang::Ecra::ObjectoCor::texto() const {
00562 return texto_;
00563 }
00564
00565 inline Slang::Cor Slang:: Ecra::ObjectoCor::fundo() const {
00566 return fundo_;
00567 }
00568
00569 inline void Slang::Ecra::ObjectoCor::texto(Cor texto) {
00570 texto_ = texto;
00571 ecra.atributos(texto_, fundo_, objecto);
00572 }
00573
00574 inline void Slang::Ecra::ObjectoCor::fundo(Cor fundo) {
00575 fundo_ = fundo;
00576 ecra.atributos(texto_, fundo_, objecto);
00577 }
00578
00579
00580
00581
00582 inline Slang::Ecra::Largura::Largura(int largura)
00583 : largura(largura) {
00584 }
00585
00586 inline Slang::Ecra::Largura
00587 Slang::Ecra::Largura::operator() (int largura) const {
00588 return Largura(largura);
00589 }
00590
00591
00592
00593
00594 inline Slang::Ecra::Linha::Linha(bool horizontal, int dimensao)
00595 : horizontal(horizontal), dimensao(dimensao) {
00596 }
00597
00598 inline Slang::Ecra::Linha Slang::Ecra::Linha::operator() (int dim) const {
00599 return Linha(horizontal, dim);
00600 }
00601
00602
00603
00604
00605 inline Slang::Ecra::Troco::Troco(Dimensao const& dimensao)
00606 : dimensao_(dimensao), dados(dimensao.linhas() * dimensao.colunas()) {
00607 }
00608
00609 inline Slang::Dimensao Slang::Ecra::Troco::dimensao() const {
00610 return dimensao_;
00611 }
00612
00613
00614
00615
00616 inline Slang::Posicao Slang::cursor(Slang::Posicao const& posicao) {
00617 return posicao;
00618 }
00619
00620 inline Slang::Posicao Slang::cursor(int linha, int coluna) {
00621 return Slang::Posicao(linha, coluna);
00622 }
00623
00624 inline Slang::Caixa Slang::caixa(Slang::Posicao const& origem,
00625 Slang::Dimensao const& dimensao) {
00626 return Caixa(origem, dimensao);
00627 }
00628
00629 inline Slang::Caixa Slang::caixa(int linha, int coluna,
00630 int linhas, int colunas) {
00631 return Caixa(Posicao(linha, coluna), Dimensao(linhas, colunas));
00632 }