/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "chamber/chamber.h" #include "chamber/common.h" #include "chamber/cga.h" #include "chamber/cursor.h" #include "chamber/dialog.h" namespace Chamber { byte *cur_str_end; byte draw_x; byte draw_y; /* Calculate number of string's character until whitespace Return current word's characters count and the next word ptr */ byte *calcStringWordWidth(byte *str, uint16 *w) { uint16 ww = 0; byte c; if ((*str & 0x3F) == 0) { str++; ww++; } while (str != cur_str_end) { if ((*str & 0x3F) == 0) break; ww++; c = *str & 0xC0; if (c != 0) { if (c == 0x40) { /*space?*/ str++; break; } ww++; } str++; } *w = ww; return str; } /* Calculate number of text's words and max word width (in chars) */ void calcStringSize(byte *str, uint16 *w, uint16 *n) { uint16 ww = 0, nw = 0, lw; byte *s = str; do { s = calcStringWordWidth(s, &lw); if (lw > ww) ww = lw; nw += 1; } while (s != cur_str_end); *w = ww; *n = nw; } /* Calculate number of text's lines with respect to set max width If a line is longer, wrap it to the next line */ uint16 calcTextLines(byte *str) { uint16 lines = 1; uint16 w, left = char_draw_max_width; while (str != cur_str_end) { str = calcStringWordWidth(str, &w); if (left > w) { left = left - w - 1; } else { lines++; left = char_draw_max_width - w - 1; } } return lines; } /*; translate 1-bit raster (4 columns per byte) to 4 2-bit color pixels*/ byte chars_color_bonw[] = {0xFF, 0xFC, 0xF3, 0xF0, 0xCF, 0xCC, 0xC3, 0xC0, 0x3F, 0x3C, 0x33, 0x30, 0x0F, 0x0C, 3, 0}; /*black on white*/ byte chars_color_bonc[] = {0x55, 0x54, 0x51, 0x50, 0x45, 0x44, 0x41, 0x40, 0x15, 0x14, 0x11, 0x10, 5, 4, 1, 0}; /*black on cyan*/ byte chars_color_wonb[] = { 0, 3, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF}; /*white on black*/ byte chars_color_wonc[] = {0x55, 0x57, 0x5D, 0x5F, 0x75, 0xF7, 0x7D, 0x7F, 0xD5, 0xD7, 0xDD, 0xDF, 0xF5, 0xF7, 0xFD, 0xFF}; /*white on cyan*/ void printStringPad(uint16 w, byte *target) { while (w--) cga_PrintChar(0, target); } byte *printWord(byte *str, byte *target) { byte c, f; if ((*str & 0x3F) == 0) goto skip_1st; while (str != cur_str_end) { f = *str; c = f & 0x3F; if (c == 0) { if ((f & 0xC0) == 0) str++; return str; } cga_PrintChar(c, target); skip_1st: ; f = *str & 0xC0; str++; if (f) { if (f == 0x80) cga_PrintChar(0x25, target); else if (f != 0x40) cga_PrintChar(0x21, target); else return str; } } string_ended = 1; return str; } byte *printStringLine(byte *str, uint16 *left, byte *target) { uint16 mw = char_draw_max_width; for (;;) { uint16 w; calcStringWordWidth(str, &w); if (mw < w) break; mw -= w; str = printWord(str, target); if (string_ended || (mw == 0)) break; mw--; cga_PrintChar(0, target); } *left = mw; return str; } byte *printStringPadded(byte *str, byte *target) { uint16 w; if (g_vm->getLanguage() != Common::EN_USA) { uint16 n; calcStringSize(str, &w, &n); if (w + 2 >= char_draw_max_width) char_draw_max_width = w + 2; } str = printStringLine(str, &w, target); if (w != 0) printStringPad(w, target); return str; } void printStringCentered(byte *str, byte *target) { byte pad = 0; uint16 ww = 0, lw; byte *s = str; do { s = calcStringWordWidth(s, &lw); ww += lw; } while (s != cur_str_end); pad = (char_draw_max_width - ww) / 2; if (pad) { char_draw_max_width -= pad; printStringPad(pad, target); } string_ended = 0; /*TODO: move me elsewhere*/ printStringPadded(str, target); } void cga_DrawTextBox(byte *msg, byte *target) { uint16 x, y, w, i; uint16 ww, nw; char_xlat_table = chars_color_bonc; if (g_vm->getLanguage() == Common::EN_USA) { calcStringSize(msg, &ww, &nw); if (ww >= char_draw_max_width) char_draw_max_width = ww; } x = draw_x * 4; y = draw_y; w = (char_draw_max_width + 2) * 4 - 2; cga_DrawHLine(x + 2, y, w - 2, 0, target); /*box top*/ for (i = 0; i < 3; i++) cga_DrawHLine(x + 1, y + 1 + i, w, 1, target); /*top margin*/ cga_DrawVLine(x, y + 2, 2, 0, target); /*left top corner 1*/ cga_DrawVLine(x + 1, y + 1, 1, 0, target); /*left top corner 2*/ cga_DrawVLine(x + w, y + 1, 1, 0, target); /*right top corner 1*/ cga_DrawVLine(x + w + 1, y + 2, 2, 0, target); /*right top corner 2*/ char_draw_coords_y = draw_y + 4; string_ended = 0; do { char_draw_coords_x = draw_x; cga_PrintChar(0x3B, target); msg = printStringPadded(msg, target); cga_PrintChar(0x3C, target); char_draw_coords_y += 6; } while (!string_ended); x = draw_x * 4; y = char_draw_coords_y; cga_DrawHLine(x + 1, y, w, 1, target); /*bottom margin*/ cga_DrawVLine(x + 1, y, 1, 0, target); /*bottom left corner 1*/ cga_DrawHLine(x + 2, y + 1, w - 2, 0, target); /*box bottom*/ cga_DrawVLine(x + 1, y, 1, 0, target); /*TODO: duplicated?*/ cga_DrawVLine(x + w, y, 1, 0, target); /*bottom right corner*/ } void drawMessage(byte *msg, byte *target) { uint16 x, y; uint16 w, h; calcStringSize(msg, &w, &h); char_draw_max_width = (h < 5) ? (w + 2) : 20; char_draw_max_height = calcTextLines(msg) * 6 + 7; x = cursor_x / 4; if (x < 9) x = 9; if (x + char_draw_max_width + 2 >= 73) x = 73 - (char_draw_max_width + 2); y = cursor_y; if (y + char_draw_max_height >= 200) y = 200 - char_draw_max_height; draw_x = x; draw_y = y; cga_BackupImageReal(CalcXY_p(x, y), char_draw_max_width + 2, char_draw_max_height); /*backup orig. screen data*/ cga_DrawTextBox(msg, target); /*draw box with text*/ promptWait(); /*wait keypress*/ cga_RestoreBackupImage(target); /*restore screen data*/ } #if 1 void debugMessage(char *msg, ...) { int16 i; byte c; byte m[256]; va_list ap; va_start(ap, msg); vsnprintf((char *)m, 256, msg, ap); va_end(ap); for (i = 0; m[i]; i++) { c = m[i]; if (c >= 'A' && c <= 'Z') c = 0x21 + (c - 'A'); else if (c >= 'a' && c <= 'z') c = 0x21 + (c - 'a'); else if (c >= '0' && c <= '9') c = 0x10 + (c - '0'); else if (c == ' ') c = 0x20; else if (c == '\n') c = 0x00; else c = 0x1F; m[i] = c; } cur_str_end = m + i; drawMessage(m, frontbuffer); } #endif } // End of namespace Chamber