Add the possibility to scroll text up and down in a virtual window

This commit is contained in:
Markus Gans 2016-10-08 02:54:32 +02:00
parent 605194b69e
commit 8328af4132
11 changed files with 209 additions and 68 deletions

View File

@ -1,4 +1,8 @@
2016-10-02 Markus Gans <guru.mail@muenster.de>
2016-10-08 Markus Gans <guru.mail@muenster.de>
* Add the possibility to scroll text up and down
in a virtual window
2016-10-06 Markus Gans <guru.mail@muenster.de>
* The input cursor is now controlled by the virtual terminal
2016-10-02 Markus Gans <guru.mail@muenster.de>

View File

@ -567,7 +567,7 @@ void FDialog::draw()
if ( isMonochron() )
setReverse(true);
clearArea();
clearArea (vwin);
drawBorder();
drawTitleBar();
setCursorPos(2, getHeight() - 1);

View File

@ -591,7 +591,7 @@ void FMenu::draw()
if ( isMonochron() )
setReverse(true);
clearArea();
clearArea (vwin);
drawBorder();
drawItems();
drawShadow();

View File

@ -60,6 +60,8 @@ static tcap_map tcap[] =
{ 0, "RI" }, // parm_right_cursor -> move #1 characters to the right (P*)
{ 0, "sc" }, // save_cursor -> save current cursor position (P)
{ 0, "rc" }, // restore_cursor -> restore cursor to save_cursor
{ 0, "sf" }, // scroll_forward -> scroll text up (P)
{ 0, "sr" }, // scroll_reverse -> scroll text down (P)
{ 0, "ti" }, // enter_ca_mode -> string to start programs using cup
{ 0, "te" }, // exit_ca_mode -> strings to end programs using cup
{ 0, "eA" }, // enable_acs -> enable alternate char set
@ -151,6 +153,8 @@ enum termcaps
t_parm_right_cursor,
t_save_cursor,
t_restore_cursor,
t_scroll_forward,
t_scroll_reverse,
t_enter_ca_mode,
t_exit_ca_mode,
t_enable_acs,

View File

@ -1752,6 +1752,7 @@ void FTerm::init()
// create virtual desktop area
createArea (vdesktop);
vdesktop->visible = true;
active_area = vdesktop;
// make stdin non-blocking
setNonBlockingInput();
@ -2683,8 +2684,8 @@ bool FTerm::updateVTermCursor (FTerm::term_area* area)
ax = area->widget->getTermX() - 1;
ay = area->widget->getTermY() - 1;
// area position
x = ax + cx - 1;
y = ay + cy - 1;
x = ax + cx;
y = ay + cy;
if ( isInsideArea(cx, cy, area)
&& isInsideTerminal(x+1, y+1)
@ -2724,8 +2725,8 @@ void FTerm::setAreaCursor (int x, int y, bool visible, FTerm::term_area* area)
if ( ! area )
return;
area->input_cursor_x = x;
area->input_cursor_y = y;
area->input_cursor_x = x - 1;
area->input_cursor_y = y - 1;
area->input_cursor_visible = visible;
updateVTerm (area);
}
@ -2939,42 +2940,97 @@ void FTerm::putArea (int ax, int ay, FTerm::term_area* area)
}
//----------------------------------------------------------------------
void FTerm::clearArea()
void FTerm::scrollAreaForward (FTerm::term_area* area)
{
term_area* area;
FWindow* window;
FWidget* widget;
FOptiAttr::char_data default_char;
int total_width;
int length;
int y_max;
FOptiAttr::char_data nc; // next character
FOptiAttr::char_data* lc; // last character
FOptiAttr::char_data* sc; // source character
FOptiAttr::char_data* dc; // destination character
if ( ! area )
return;
if ( area->height <= 1 )
return;
length = area->width;
total_width = area->width + area->right_shadow;
y_max = area->height - 1;
for (int y=0; y < y_max; y++)
{
int pos1 = y * total_width;
int pos2 = (y+1) * total_width;
sc = &area->text[pos2];
dc = &area->text[pos1];
std::memcpy (dc, sc, sizeof(FOptiAttr::char_data) * unsigned(length));
area->changes[y].xmin = 0;
area->changes[y].xmax = uInt(area->width - 1);
}
// insert a new line below
lc = &area->text[(y_max * total_width) - area->right_shadow - 1];
std::memcpy (&nc, lc, sizeof(FOptiAttr::char_data));
nc.code = ' ';
dc = &area->text[y_max * total_width];
std::fill_n (dc, area->width, nc);
area->changes[y_max].xmin = 0;
area->changes[y_max].xmax = uInt(area->width - 1);
}
//----------------------------------------------------------------------
void FTerm::scrollAreaReverse (FTerm::term_area* area)
{
int total_width;
int length;
FOptiAttr::char_data nc; // next character
FOptiAttr::char_data* lc; // last character
FOptiAttr::char_data* sc; // source character
FOptiAttr::char_data* dc; // destination character
if ( ! area )
return;
if ( area->height <= 1 )
return;
length = area->width;
total_width = area->width + area->right_shadow;
for (int y=area->height-1; y > 0; y--)
{
int pos1 = (y-1) * total_width;
int pos2 = y * total_width;
sc = &area->text[pos1];
dc = &area->text[pos2];
std::memcpy (dc, sc, sizeof(FOptiAttr::char_data) * unsigned(length));
area->changes[y].xmin = 0;
area->changes[y].xmax = uInt(area->width - 1);
}
// insert a new line above
lc = &area->text[total_width];
std::memcpy (&nc, lc, sizeof(FOptiAttr::char_data));
nc.code = ' ';
dc = &area->text[0];
std::fill_n (dc, area->width, nc);
area->changes[0].xmin = 0;
area->changes[0].xmax = uInt(area->width - 1);
}
//----------------------------------------------------------------------
void FTerm::clearArea (FTerm::term_area* area)
{
FOptiAttr::char_data nc; // next character
int total_width;
uInt w;
default_char.code = ' ';
default_char.fg_color = next_attribute.fg_color;
default_char.bg_color = next_attribute.bg_color;
default_char.bold = next_attribute.bold;
default_char.dim = next_attribute.dim;
default_char.italic = next_attribute.italic;
default_char.underline = next_attribute.underline;
default_char.blink = next_attribute.blink;
default_char.reverse = next_attribute.reverse;
default_char.standout = next_attribute.standout;
default_char.invisible = next_attribute.invisible;
default_char.protect = next_attribute.protect;
default_char.crossed_out = next_attribute.crossed_out;
default_char.dbl_underline = next_attribute.dbl_underline;
default_char.alt_charset = next_attribute.alt_charset;
default_char.pc_charset = next_attribute.pc_charset;
default_char.transparent = next_attribute.transparent;
default_char.trans_shadow = next_attribute.trans_shadow;
default_char.inherit_bg = next_attribute.inherit_bg;
widget = static_cast<FWidget*>(this);
window = FWindow::getWindowWidget(widget);
if ( window )
area = window->getVWin();
else
area = vdesktop;
// clear with the current attributes and space characters
std::memcpy (&nc, &next_attribute, sizeof(FOptiAttr::char_data));
nc.code = ' ';
if ( ! area )
return;
@ -2985,17 +3041,17 @@ void FTerm::clearArea()
if ( area->right_shadow == 0 )
{
int area_size = area->width * area->height;
std::fill_n (area->text, area_size, default_char);
std::fill_n (area->text, area_size, nc);
}
else
{
FOptiAttr::char_data t_char = default_char;
FOptiAttr::char_data t_char = nc;
t_char.transparent = true;
for (int y=0; y < area->height; y++)
{
int pos = y * total_width;
std::fill_n (&area->text[pos], total_width, default_char);
std::fill_n (&area->text[pos], total_width, nc);
std::fill_n (&area->text[pos+area->width], area->right_shadow, t_char);
}
@ -3012,9 +3068,9 @@ void FTerm::clearArea()
area->changes[i].xmin = 0;
area->changes[i].xmax = w - 1;
if ( default_char.transparent
|| default_char.trans_shadow
|| default_char.inherit_bg )
if ( nc.transparent
|| nc.trans_shadow
|| nc.inherit_bg )
area->changes[i].trans_count = w;
else if ( area->right_shadow != 0 )
area->changes[i].trans_count = uInt(area->right_shadow);
@ -4242,6 +4298,32 @@ bool FTerm::setNonBlockingInput (bool on)
return non_blocking_stdin;
}
//----------------------------------------------------------------------
bool FTerm::scrollTermForward()
{
if ( tcap[t_scroll_forward].string )
{
putstring (tcap[t_scroll_forward].string);
std::fflush(stdout);
return true;
}
return false;
}
//----------------------------------------------------------------------
bool FTerm::scrollTermReverse()
{
if ( tcap[t_scroll_reverse].string )
{
putstring (tcap[t_scroll_reverse].string);
std::fflush(stdout);
return true;
}
return false;
}
//----------------------------------------------------------------------
bool FTerm::setUTF8 (bool on) // UTF-8 (Unicode)
{

View File

@ -313,7 +313,9 @@ class FTerm
void getArea (int, int, int, int, FTerm::term_area*);
void putArea (const FPoint&, FTerm::term_area*);
void putArea (int, int, FTerm::term_area*);
void clearArea();
static void scrollAreaForward (FTerm::term_area*);
static void scrollAreaReverse (FTerm::term_area*);
void clearArea (FTerm::term_area*);
FOptiAttr::char_data getCharacter (int, const FPoint&, FTerm*);
FOptiAttr::char_data getCharacter (int, int, int, FTerm*);
FOptiAttr::char_data getCoveredCharacter (const FPoint&, FTerm*);
@ -413,6 +415,9 @@ class FTerm
static bool setNonBlockingInput();
static bool unsetNonBlockingInput();
static bool scrollTermForward();
static bool scrollTermReverse();
static bool setUTF8 (bool);
static bool setUTF8();
static bool unsetUTF8();
@ -424,6 +429,7 @@ class FTerm
static bool unsetRawMode();
static bool setCookedMode();
static bool isRaw();
static FString getAnswerbackMsg();
static FString getSecDA();

View File

@ -130,7 +130,7 @@ void FToolTip::draw()
if ( getMaxColor() < 16 )
setBold();
clearArea();
clearArea (vwin);
drawBorder();
for (int i=0; i < int(text_num_lines); i++)

View File

@ -143,7 +143,7 @@ void FWidget::init()
foreground_color = wc.term_fg;
background_color = wc.term_bg;
setColor();
clearArea();
clearArea(vdesktop);
accelerator_list = new Accelerators();
}
@ -369,29 +369,31 @@ void FWidget::setColorTheme()
//----------------------------------------------------------------------
FTerm::term_area* FWidget::getPrintArea()
{
// returns the print area of this object
if ( print_area )
return print_area;
else
{
FWidget* window = FWindow::getWindowWidget(this);
FWidget* obj = static_cast<FWidget*>(this);
FWidget* p_obj = static_cast<FWidget*>(obj->getParent());
if ( window )
while ( ! obj->vwin && p_obj )
{
term_area* area = window->getVWin();
if ( area )
{
print_area = area;
return area;
}
else
return 0;
obj = p_obj;
p_obj = static_cast<FWidget*>(p_obj->getParent());
}
if ( obj->vwin )
{
print_area = obj->vwin;
return print_area;
}
else
return 0;
}
return vdesktop;
}
// protected methods of FWidget
//----------------------------------------------------------------------
void FWidget::adjustSize()
@ -1227,7 +1229,7 @@ void FWidget::redraw()
terminal_updates = false;
// clean desktop
setColor (wc.term_fg, wc.term_bg);
clearArea();
clearArea (vdesktop);
}
else if ( ! visible )
return;

View File

@ -506,6 +506,7 @@ class FWidget : public FObject, public FTerm
void printPos (const FPoint&);
void printPos (register int, register int);
FPoint getPrintPos() const;
static void setNormal();
@ -937,6 +938,15 @@ inline void FWidget::printPos (register int x, register int y)
offset.getY1() + adjust_wsize.getY() - 1 + y );
}
//----------------------------------------------------------------------
inline FPoint FWidget::getPrintPos() const
{
int cx = cursor->getX();
int cy = cursor->getY();
return FPoint ( cx - offset.getX1() - adjust_wsize.getX() + 1
, cy - offset.getY1() - adjust_wsize.getY() + 1 );
}
//----------------------------------------------------------------------
inline void FWidget::setNormal()
{

View File

@ -34,7 +34,23 @@ keyboard::keyboard (FWidget* parent)
void keyboard::onKeyPress (FKeyEvent* ev)
{
int key_id = ev->key();
std::printf("Key %s (id %d)\n\r", getKeyName(key_id).c_str(), key_id);
bool is_last_line = false;
if ( getPrintPos().getY() == getLineNumber() )
is_last_line = true;
printf ("Key %s (id %d)\n", getKeyName(key_id).c_str(), key_id);
if ( is_last_line )
{
scrollAreaForward (vdesktop);
if ( ! scrollTermForward() )
putArea (getTermPos(), vdesktop);
}
setAreaCursor (1, getPrintPos().getY(), true, vdesktop);
}
//----------------------------------------------------------------------
@ -49,12 +65,12 @@ void keyboard::draw()
{
setNormal();
setColor(fc::Default, fc::Default);
clearArea();
clearArea (vdesktop);
printPosTerm (1,1);
print ("---------------\n");
print ("Press Q to quit\n");
print ("---------------\n");
setCursorPos (1,5);
setAreaCursor (1, 4, true, vdesktop);
}
//----------------------------------------------------------------------

View File

@ -39,7 +39,24 @@ timer::timer (FWidget* parent)
//----------------------------------------------------------------------
void timer::onTimer (FTimerEvent* ev)
{
std::printf("timer event, id %d\n\r", ev->timerId() );
bool is_last_line = false;
int timer_id = ev->timerId();
if ( getPrintPos().getY() == getLineNumber() )
is_last_line = true;
setColor (short(1 + timer_id), fc::Default);
printf ("timer event, id %d\n", timer_id );
if ( is_last_line )
{
scrollAreaForward (vdesktop);
if ( ! scrollTermForward() )
putArea (getTermPos(), vdesktop);
}
setAreaCursor (1, getPrintPos().getY(), true, vdesktop);
}
//----------------------------------------------------------------------
@ -54,12 +71,12 @@ void timer::draw()
{
setNormal();
setColor (fc::Default, fc::Default);
clearArea();
clearArea (vdesktop);
printPosTerm (1,1);
print ("---------------\n");
print ("Press Q to quit\n");
print ("---------------\n");
setCursorPos (1,4);
setAreaCursor (1, 4, true, vdesktop);
}