Category : Files from Magazines
Archive   : DFPP01.ZIP
Filename : TEXTBOX.CPP

 
Output of file : TEXTBOX.CPP contained in archive : DFPP01.ZIP

// ------------- textbox.cpp

#include "desktop.h"
#include "textbox.h"
#include "scrolbar.h"

// ----------- common constructor code
void TextBox::OpenWindow()
{
windowtype = TextboxWindow;
if (windowstate == CLOSED)
Control::OpenWindow();
text = NULL;
bufflen = InitialBufferSize;
hscrollbar = vscrollbar = NULL;
TextPointers = NULL;
ClearText();
SetColors();
}

void TextBox::CloseWindow()
{
ClearText();
if (hscrollbar != NULL)
delete hscrollbar;
if (vscrollbar != NULL)
delete vscrollbar;
Control::CloseWindow();
}


// ------ show the textbox
void TextBox::Show()
{
if ((attrib & HSCROLLBAR) && hscrollbar == NULL) {
hscrollbar = new ScrollBar(HORIZONTAL, this);
hscrollbar->SetAttribute(FRAMEWND);
}
if ((attrib & VSCROLLBAR) && vscrollbar == NULL) {
vscrollbar = new ScrollBar(VERTICAL, this);
vscrollbar->SetAttribute(FRAMEWND);
}
Control::Show();
}

// ------------ build the text line pointers
void TextBox::BuildTextPointers()
{
textwidth = wlines = 0;
// ---- count the lines of text
char *cp1, *cp = *text;
while (*cp) {
wlines++;
while (*cp && *cp != '\n')
cp++;
if (*cp)
cp++;
}
// ----- build the pointer array
delete TextPointers;
TextPointers = new unsigned int[wlines];
unsigned int off;
cp = *text;
wlines = 0;
while (*cp) {
off = (unsigned int) (cp - *text);
*(TextPointers + wlines++) = off;
cp1 = cp;
while (*cp && *cp != '\n')
cp++;
textwidth = max(textwidth, (unsigned int) (cp - cp1));
if (*cp)
cp++;
}
}

// --------- add a line of text to the textbox
void TextBox::AddText(char *txt)
{
String tx(txt);
int len = tx.Strlen();
if (tx[len-1] != '\n')
textlen++;
textlen += len;
if (text == NULL)
text = new String(bufflen);
if (textlen > text->StrBufLen())
text->ChangeLength(max(bufflen, textlen));
*text += tx;
if (*text[len-1] != '\n')
*text += String("\n");
BuildTextPointers();
}

// --------- set the textbox's text buffer to new text
void TextBox::SetText(char *txt)
{
ClearText();
AddText(txt);
}

// ------ set the length of the text buffer
void TextBox::SetTextLength(unsigned int len)
{
if (text != NULL)
text->ChangeLength(len);
bufflen = len;
}

// --------- clear the text from the textbox
void TextBox::ClearText()
{
if (text != NULL)
delete text;
textlen = 0;
wlines = 0;
textwidth = 0;
wtop = wleft = 0;
ClearTextBlock();
if (TextPointers != NULL)
delete TextPointers;
}

// -------- set the fg/bg colors for the window
void TextBox::SetColors()
{
colors.fg = BLACK;
colors.bg = LIGHTGRAY;
colors.sfg = LIGHTGRAY;
colors.sbg = BLACK;
colors.ffg = BLACK;
colors.fbg = LIGHTGRAY;
colors.hfg = BLACK;
colors.hbg = LIGHTGRAY;
shortcutfg = BLUE;
}

// ------- extract a text line
String TextBox::ExtractTextLine(int lno)
{
char *lp = TextLine(lno);
int offset = lp - (char *) *text;
for (int len = 0; *(lp+len) && *(lp+len) != '\n'; len++)
;
return text->mid(len, offset);
}

// ---- display a line with a shortcut key character
void TextBox::WriteShortcutLine(int lno, int fg, int bg)
{
String sc = ExtractTextLine(lno);
int x = sc.Strlen();
int y = lno-wtop;
x -= DisplayShortcutField(sc, 0, y, fg, bg);
// --------- pad the line
int wd = ClientWidth() - x;
if (wd > 0)
WriteClientString(String(wd, ' '), x, y, fg, bg);
}

// ---- display a shortcut field character
int TextBox::DisplayShortcutField(String sc, int x, int y,
int fg, int bg)
{
int scs = 0;
int off = sc.FindChar(SHORTCUTCHAR);
if (off != -1) {
scs++;
if (off != 0) {
String ls = sc.left(off);
WriteClientString(ls, x, y, fg, bg);
}
WriteClientChar(sc[off+1], x+off, y, shortcutfg, bg);
int len = sc.Strlen()-off-2;
if (len > 0) {
String rs = sc.right(len);
scs += DisplayShortcutField(rs, x+off+1, y, fg, bg);
}
}
else
WriteClientString(sc, x, y, fg, bg);
return scs;
}

// ------- write a text line to the textbox
void TextBox::WriteTextLine(int lno, int fg, int bg)
{
if (lno < wtop || lno >= wtop + ClientHeight())
return;
int wd = ClientWidth();
String tl = ExtractTextLine(lno);
String ln = tl.mid(wd, wleft);
int dif = wd-ln.Strlen();
if (dif > 0)
ln = ln + String(dif, ' '); // pad the line with spaces
// ----- display the line
WriteClientString(ln, 0, lno-wtop, fg, bg);
}

// ---------- paint the textbox
void TextBox::Paint()
{
if (text == NULL)
Control::Paint();
else {
int ht = ClientHeight();
int wd = ClientWidth();
int fg = colors.fg;
int bg = colors.bg;
for (int i = 0; i < min(wlines-wtop,ht); i++)
WriteTextLine(wtop+i, fg, bg);
// ---- pad the bottom lines in the window
String line(wd, ' ');
while (i < ht)
WriteClientString(line, 0, i++, fg, bg);
if (resetscrollbox)
SetScrollBoxes();
resetscrollbox = False;
}
}

// ------ process a textbox keystroke
void TextBox::Keyboard(int key)
{
switch (key) {
case UP:
if (ClientTop() == ClientBottom())
break;
ScrollDown();
return;
case DN:
if (ClientTop() == ClientBottom())
break;
ScrollUp();
return;
case FWD:
ScrollLeft();
return;
case BS:
ScrollRight();
return;
case PGUP:
PageUp();
return;
case PGDN:
PageDown();
return;
case CTRL_PGUP:
PageLeft();
return;
case CTRL_PGDN:
PageRight();
return;
case HOME:
Home();
return;
case END:
End();
return;
default:
break;
}
Control::Keyboard(key);
}

// ------- scroll up one line
void TextBox::ScrollUp()
{
if (wtop < wlines-1) {
int fg = colors.fg;
int bg = colors.bg;
desktop.screen().Scroll(ClientRect(), 1, fg, bg);
wtop++;
int ln = wtop+ClientHeight()-1;
if (ln < wlines)
WriteTextLine(ln, fg, bg);
SetScrollBoxes();
}
}

// ------- scroll down one line
void TextBox::ScrollDown()
{
if (wtop) {
int fg = colors.fg;
int bg = colors.bg;
desktop.screen().Scroll(ClientRect(), 0, fg, bg);
--wtop;
WriteTextLine(wtop, fg, bg);
SetScrollBoxes();
}
}

// ------- scroll left one character
void TextBox::ScrollLeft()
{
if (wleft < textwidth-1)
wleft++;
Paint();
}

// ------- scroll right one character
void TextBox::ScrollRight()
{
if (wleft > 0)
--wleft;
Paint();
}

// ------- page up one screenfull
void TextBox::PageUp()
{
if (wtop) {
wtop -= ClientHeight();
if (wtop < 0)
wtop = 0;
resetscrollbox = True;
Paint();
}
}

// ------- page down one screenfull
void TextBox::PageDown()
{
if (wtop < wlines-1) {
wtop += ClientHeight();
if (wlines < wtop)
wtop = wlines-1;
resetscrollbox = True;
Paint();
}
}

// ------- page right one screenwidth
void TextBox::PageRight()
{
if (wleft < textwidth-1) {
wleft += ClientWidth();
if (textwidth < wleft)
wleft = textwidth-1;
resetscrollbox = True;
Paint();
}
}

// ------- page left one screenwidth
void TextBox::PageLeft()
{
if (wleft) {
wleft -= ClientWidth();
if (wleft < 0)
wleft = 0;
resetscrollbox = True;
Paint();
}
}

// ----- move to the first line of the textbox
void TextBox::Home()
{
wtop = 0;
Paint();
}

// ----- move to the last line of the textbox
void TextBox::End()
{
wtop = wlines-ClientHeight();
if (wtop < 0)
wtop = 0;
Paint();
}

// ----- position the scroll boxes
void TextBox::SetScrollBoxes()
{
if (vscrollbar != NULL)
vscrollbar->TextPosition(wlines ? (wtop*100)/wlines : 0);
if (hscrollbar != NULL)
hscrollbar->TextPosition(textwidth ? (wleft*100)/textwidth : 0);
}

// ---- compute the horizontal page position
void TextBox::HorizontalPagePosition(int pct)
{
wleft = (textwidth * pct) / 100;
Paint();
}

// ---- compute the vertical page position
void TextBox::VerticalPagePosition(int pct)
{
wtop = (wlines * pct) / 100;
Paint();
}