Files
2026-02-02 04:50:13 +01:00

274 lines
6.4 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/spacebar/boflib/gui/text_box.h"
namespace Bagel {
namespace SpaceBar {
#define DEFAULT_PAGE_SIZE 10
#define DEFAULT_WEIGHT TEXT_NORMAL
#define DEFAULT_POINT_SIZE FONT_12POINT
#define DEFAULT_COLOR CTEXT_COLOR
CBofTextBox::CBofTextBox() {
// Inits
_pDestWindow = nullptr;
_pDestBitmap = nullptr;
_pTextField = nullptr;
_nWeight = DEFAULT_WEIGHT;
_nPointSize = DEFAULT_POINT_SIZE;
_cTextColor = DEFAULT_COLOR;
_nTextFont = FONT_DEFAULT;
_nPageSize = DEFAULT_PAGE_SIZE;
_nCurrentLine = 0;
_nCurrentIndex = 0;
_nNumLines = 0;
}
CBofTextBox::CBofTextBox(CBofWindow *pWindow, const CBofRect *pRect, const CBofString &cText) {
assert(pWindow != nullptr);
assert(pRect != nullptr);
// Inits
_pDestWindow = nullptr;
_pDestBitmap = nullptr;
_pTextField = nullptr;
_nWeight = DEFAULT_WEIGHT;
_nPointSize = DEFAULT_POINT_SIZE;
_cTextColor = DEFAULT_COLOR;
_nPageSize = DEFAULT_PAGE_SIZE;
_nCurrentLine = 0;
_nCurrentIndex = 0;
_nNumLines = 0;
_nTextFont = FONT_DEFAULT;
setText(cText);
setBox(pRect);
setDisplay(pWindow);
}
CBofTextBox::CBofTextBox(CBofBitmap *pBitmap, const CBofRect *pRect, const CBofString &cText) {
assert(pBitmap != nullptr);
assert(pRect != nullptr);
// Inits
_pDestWindow = nullptr;
_pDestBitmap = nullptr;
_pTextField = nullptr;
_nWeight = DEFAULT_WEIGHT;
_nPointSize = DEFAULT_POINT_SIZE;
_cTextColor = DEFAULT_COLOR;
_nPageSize = DEFAULT_PAGE_SIZE;
_nCurrentLine = 0;
_nCurrentIndex = 0;
_nNumLines = 0;
_nTextFont = FONT_DEFAULT;
setText(cText);
setBox(pRect);
setDisplay(pBitmap);
}
CBofTextBox::~CBofTextBox() {
assert(isValidObject(this));
if (_pTextField != nullptr) {
delete _pTextField;
_pTextField = nullptr;
}
_pDestWindow = nullptr;
_pDestBitmap = nullptr;
}
ErrorCode CBofTextBox::setBox(const CBofRect *pRect) {
assert(isValidObject(this));
assert(pRect != nullptr);
// Remove previous text field (if any)
delete _pTextField;
_pTextField = nullptr;
// Create a new text field the size of the box we want
_pTextField = new CBofText(pRect, JUSTIFY_WRAP);
return _errCode;
}
void CBofTextBox::setDisplay(CBofWindow *pWindow) {
assert(isValidObject(this));
assert(pWindow != nullptr);
_pDestWindow = pWindow;
_pDestBitmap = nullptr;
}
void CBofTextBox::setDisplay(CBofBitmap *pBitmap) {
assert(isValidObject(this));
assert(pBitmap != nullptr);
_pDestBitmap = pBitmap;
_pDestWindow = nullptr;
}
void CBofTextBox::setTextAttribs(const int nSize, const int nWeight, const COLORREF cColor, const int nFont) {
assert(isValidObject(this));
_nPointSize = nSize;
_nWeight = nWeight;
_cTextColor = cColor;
_nTextFont = nFont;
}
void CBofTextBox::setText(const CBofString &cString) {
_cBuffer = cString;
assert(_cBuffer.getLength() != 0);
_cBuffer.replaceStr("\r\n", "\n");
_cBuffer.replaceStr("\r", "\n");
_nCurrentLine = 0;
_nCurrentIndex = 0;
_nNumLines = _cBuffer.findNumOccurrences("\n");
}
int CBofTextBox::getIndex(const int nLine) {
assert(nLine >= 0 && nLine <= _nNumLines);
// Find the index into our buffer that represents the top left of the
// buffer that is nLine from current the beginning of the buffer.
const char *pszCur, *pszBuffer;
const char *pszLast = pszCur = pszBuffer = _cBuffer;
for (int i = 0; i < nLine; i++) {
pszLast = pszCur;
pszCur = strstr(pszCur, "\n");
// Make sure we don't go too far (nLines is invalid)
assert(pszCur != nullptr);
pszCur++;
}
int nChars = pszCur - pszBuffer;
if (nLine == _nNumLines) {
nChars = pszLast - pszBuffer;
_nCurrentLine--;
}
return nChars;
}
ErrorCode CBofTextBox::scrollUp(const int nLines) {
// Make scroll a no-op if all the lines in the box appear on one screen.
if (_nNumLines <= _nPageSize) {
return scrollTo(_nCurrentLine);
}
int nNewLine = _nCurrentLine - nLines;
if (nNewLine < 0) {
nNewLine = 0;
} else if (nNewLine > (_nNumLines - _nPageSize)) {
// If the line requested to be the top of the page
// would cause fewer than _nPageSize lines to be displayed,
// snap nNewLine to be the top of the last full page.
//
nNewLine = (_nNumLines - _nPageSize);
}
return scrollTo(nNewLine);
}
ErrorCode CBofTextBox::scrollTo(const int nLine) {
assert(isValidObject(this));
assert(nLine >= 0 && nLine <= _nNumLines);
_nCurrentIndex = getIndex(nLine);
_nCurrentLine = nLine;
// Show the text box
display();
return _errCode;
}
ErrorCode CBofTextBox::display() {
assert(isValidObject(this));
assert(_nCurrentLine >= 0 && _nCurrentLine <= _nNumLines);
assert(_nCurrentIndex >= 0 && _nCurrentIndex < _cBuffer.getLength());
// The actual text box must have been created before it can be displayed
assert(_pTextField != nullptr);
// If painting to a window
if (_pDestWindow != nullptr) {
_pTextField->display(_pDestWindow, _cBuffer.mid(_nCurrentIndex), _nPointSize, _nWeight, _cTextColor, _nTextFont);
} else {
// Otherwise, must be painting to a bitmap
assert(_pDestBitmap != nullptr);
_pTextField->display(_pDestBitmap, _cBuffer.mid(_nCurrentIndex), _nPointSize, _nWeight, _cTextColor, _nTextFont);
}
return _errCode;
}
ErrorCode CBofTextBox::erase() {
assert(isValidObject(this));
// The actual text box must have been created before it can be displayed
assert(_pTextField != nullptr);
if (_pDestWindow != nullptr) {
_errCode = _pTextField->erase(_pDestWindow);
} else {
assert(_pDestBitmap != nullptr);
_errCode = _pTextField->erase(_pDestBitmap);
}
return _errCode;
}
void CBofTextBox::flushBackground() {
assert(isValidObject(this));
if (_pTextField != nullptr) {
_pTextField->flushBackground();
}
}
} // namespace SpaceBar
} // namespace Bagel