Add the possibility to scroll text up and down in a virtual window
This commit is contained in:
parent
605194b69e
commit
8328af4132
|
@ -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>
|
||||
|
|
|
@ -567,7 +567,7 @@ void FDialog::draw()
|
|||
if ( isMonochron() )
|
||||
setReverse(true);
|
||||
|
||||
clearArea();
|
||||
clearArea (vwin);
|
||||
drawBorder();
|
||||
drawTitleBar();
|
||||
setCursorPos(2, getHeight() - 1);
|
||||
|
|
|
@ -591,7 +591,7 @@ void FMenu::draw()
|
|||
if ( isMonochron() )
|
||||
setReverse(true);
|
||||
|
||||
clearArea();
|
||||
clearArea (vwin);
|
||||
drawBorder();
|
||||
drawItems();
|
||||
drawShadow();
|
||||
|
|
|
@ -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,
|
||||
|
|
166
src/fterm.cpp
166
src/fterm.cpp
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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();
|
||||
obj = p_obj;
|
||||
p_obj = static_cast<FWidget*>(p_obj->getParent());
|
||||
}
|
||||
|
||||
if ( area )
|
||||
if ( obj->vwin )
|
||||
{
|
||||
print_area = area;
|
||||
return area;
|
||||
print_area = obj->vwin;
|
||||
return print_area;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue