diff --git a/ChangeLog b/ChangeLog index 26fdc19d..7c8ad0b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2016-10-11 Markus Gans + * Separate the virtual terminal into a own class vterm + 2016-10-09 Markus Gans * Remove some duplicate code diff --git a/src/Makefile.am b/src/Makefile.am index b0b5d0a2..a8170249 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,6 +38,7 @@ libfinal_la_SOURCES = \ ftextview.cpp \ fstatusbar.cpp \ fterm.cpp \ + fvterm.cpp \ fevent.cpp \ foptiattr.cpp \ foptimove.cpp \ @@ -87,6 +88,7 @@ finalcutinclude_HEADERS = \ fstring.h \ ftcap_map.h \ fterm.h \ + fvterm.cpp \ ftextview.h \ ftogglebutton.h \ fwidget.h \ diff --git a/src/Makefile.clang b/src/Makefile.clang index dbe59036..bd57fd39 100644 --- a/src/Makefile.clang +++ b/src/Makefile.clang @@ -38,6 +38,7 @@ INCLUDE_HEADERS = \ fstatusbar.h \ fstring.h \ fterm.h \ + fvterm.h \ ftextview.h \ ftogglebutton.h \ fwidget.h \ @@ -83,6 +84,7 @@ OBJS = \ ftextview.o \ fstatusbar.o \ fterm.o \ + fvterm.o \ fevent.o \ foptiattr.o \ foptimove.o \ diff --git a/src/Makefile.gcc b/src/Makefile.gcc index 21a3ef38..d99c74c6 100644 --- a/src/Makefile.gcc +++ b/src/Makefile.gcc @@ -38,6 +38,7 @@ INCLUDE_HEADERS = \ fstatusbar.h \ fstring.h \ fterm.h \ + fvterm.h \ ftextview.h \ ftogglebutton.h \ fwidget.h \ @@ -83,6 +84,7 @@ OBJS = \ ftextview.o \ fstatusbar.o \ fterm.o \ + fvterm.o \ fevent.o \ foptiattr.o \ foptimove.o \ diff --git a/src/Makefile.in b/src/Makefile.in index e85a82f4..bc755485 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -134,8 +134,9 @@ am_libfinal_la_OBJECTS = fstring.lo fpoint.lo frect.lo fscrollbar.lo \ flabel.lo flistbox.lo fmenu.lo fdialoglistmenu.lo fmenubar.lo \ fmenuitem.lo fradiomenuitem.lo fcheckmenuitem.lo fmenulist.lo \ fdialog.lo fwindow.lo fmessagebox.lo ftooltip.lo \ - ffiledialog.lo ftextview.lo fstatusbar.lo fterm.lo fevent.lo \ - foptiattr.lo foptimove.lo fapp.lo fwidget.lo fobject.lo + ffiledialog.lo ftextview.lo fstatusbar.lo fterm.lo fvterm.lo \ + fevent.lo foptiattr.lo foptimove.lo fapp.lo fwidget.lo \ + fobject.lo libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -402,6 +403,7 @@ libfinal_la_SOURCES = \ ftextview.cpp \ fstatusbar.cpp \ fterm.cpp \ + fvterm.cpp \ fevent.cpp \ foptiattr.cpp \ foptimove.cpp \ @@ -449,6 +451,7 @@ finalcutinclude_HEADERS = \ fstring.h \ ftcap_map.h \ fterm.h \ + fvterm.cpp \ ftextview.h \ ftogglebutton.h \ fwidget.h \ @@ -566,6 +569,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftextview.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftogglebutton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftooltip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvterm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fwidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fwindow.Plo@am__quote@ diff --git a/src/fapp.cpp b/src/fapp.cpp index e26713af..362fa38f 100644 --- a/src/fapp.cpp +++ b/src/fapp.cpp @@ -36,7 +36,6 @@ FApplication::FApplication (int& _argc, char**& _argv) : FWidget(0) , app_argc(_argc) , app_argv(_argv) - , skipped_terminal_update(0) , key(0) #ifdef F_HAVE_LIBGPM , gpm_ev() @@ -89,9 +88,11 @@ void FApplication::init() time_mousepressed.tv_sec = 0; time_mousepressed.tv_usec = 0; x11_button_state = 0x23; + #ifdef F_HAVE_LIBGPM gpm_ev.x = -1; #endif + zero_point = new FPoint(0,0); event_queue = new std::deque; // init arrays with '\0' @@ -276,6 +277,7 @@ void FApplication::processKeyboardEvent() flush_out(); #ifdef F_HAVE_LIBGPM + if ( gpm_mouse_enabled ) { gpmMouseEvent = false; @@ -296,8 +298,11 @@ void FApplication::processKeyboardEvent() } else isKeyPressed = KeyPressed(); + #else // without gpm + isKeyPressed = KeyPressed(); + #endif // F_HAVE_LIBGPM if ( isKeyPressed ) @@ -1605,7 +1610,7 @@ void FApplication::processMouseEvent() sendEvent (clicked_widget, &m_down_ev); // gnome-terminal sends no released on middle click - if ( gnome_terminal ) + if ( isGnomeTerminal() ) clicked_widget = 0; } else if ( b_state.middle_button == Released ) @@ -1714,32 +1719,6 @@ int FApplication::processTimerEvent() return activated; } -//---------------------------------------------------------------------- -void FApplication::processTerminalUpdate() -{ - const int max_skip = 8; - - if ( terminal_update_pending ) - { - if ( ! unprocessedInput() ) - { - updateTerminal(); - terminal_update_pending = false; - skipped_terminal_update = 0; - } - else if ( skipped_terminal_update > max_skip ) - { - force_terminal_update = true; - updateTerminal(); - force_terminal_update = false; - terminal_update_pending = false; - skipped_terminal_update = 0; - } - else - skipped_terminal_update++; - } -} - //---------------------------------------------------------------------- void FApplication::processCloseWidget() { diff --git a/src/fapp.h b/src/fapp.h index 77071040..47a7613f 100644 --- a/src/fapp.h +++ b/src/fapp.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ @@ -31,8 +36,6 @@ #ifndef _FAPPLICATION_H #define _FAPPLICATION_H -#include // need for gpm keyboard modifiers -#include // need for gettimeofday #include #include @@ -62,7 +65,6 @@ class FApplication : public FWidget static int loop_level; static bool process_timer_event; static FPoint* zero_point; - int skipped_terminal_update; int key; char k_buf[1024]; char x11_mouse[4]; @@ -70,6 +72,7 @@ class FApplication : public FWidget char urxvt_mouse[13]; #ifdef F_HAVE_LIBGPM + Gpm_Event gpm_ev; bool gpmMouseEvent; enum gpmEventType @@ -78,6 +81,7 @@ class FApplication : public FWidget keyboard_event = 1, mouse_event = 2 }; + #endif enum btn_state @@ -138,14 +142,15 @@ class FApplication : public FWidget bool parseUrxvtMouse(); #ifdef F_HAVE_LIBGPM + int gpmEvent (bool = true); bool processGpmEvent(); + #endif void processMouseEvent(); void processResizeEvent(); int processTimerEvent(); - void processTerminalUpdate(); void processCloseWidget(); bool processNextEvent(); diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 3d835c98..32535a59 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -182,7 +182,7 @@ void FButton::draw() for (int y=1; y <= getHeight(); y++) { - printPos (1, y); + setPrintPos (1, y); print (' '); // clear one left █ } @@ -241,7 +241,7 @@ void FButton::draw() for (int y=0; y < getHeight(); y++) { - printPos (1+d, 1+y); + setPrintPos (1+d, 1+y); print (space); // full block █ } } @@ -256,7 +256,7 @@ void FButton::draw() for (int y=0; y < getHeight(); y++) { - printPos (1+d, 1+y); + setPrintPos (1+d, 1+y); // Cygwin terminal use IBM Codepage 850 if ( isCygwinTerminal() ) @@ -282,7 +282,7 @@ void FButton::draw() if ( isMonochron() ) setReverse(true); - printPos (1+getWidth(), y); + setPrintPos (1+getWidth(), y); print (' '); // clear right if ( isMonochron() ) @@ -301,7 +301,7 @@ void FButton::draw() else j=0; - printPos (1+margin+d, 1+j); + setPrintPos (1+margin+d, 1+j); setColor (button_fg, button_bg); for (x=0; x < i; x++) @@ -353,14 +353,14 @@ void FButton::draw() { for (i=0; i < j; i++) { - printPos (2+d, 1+i); + setPrintPos (2+d, 1+i); for (int z=1; z < getWidth(); z++) print (space); // █ } for (i=j+1; i < getHeight(); i++) { - printPos (2+d, 1+i); + setPrintPos (2+d, 1+i); for (int z=1; z < getWidth(); z++) print (space); // █ @@ -525,7 +525,7 @@ void FButton::hide() for (int y=0; y < getHeight()+s+(f << 1); y++) { - printPos (1-f, 1+y-f); + setPrintPos (1-f, 1+y-f); print (blank); } diff --git a/src/fbutton.h b/src/fbutton.h index 7c4e5d53..97876af3 100644 --- a/src/fbutton.h +++ b/src/fbutton.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fbuttongroup.cpp b/src/fbuttongroup.cpp index 30bc2e91..4c9bbdfc 100644 --- a/src/fbuttongroup.cpp +++ b/src/fbuttongroup.cpp @@ -252,9 +252,9 @@ void FButtonGroup::drawLabel() length--; if ( border ) - printPos (2, 1); + setPrintPos (2, 1); else - printPos (0, 1); + setPrintPos (0, 1); if ( isEnabled() ) setColor(wc.label_emphasis_fg, wc.label_bg); @@ -330,7 +330,7 @@ void FButtonGroup::hide() for (int y=0; y < getHeight(); y++) { - printPos (1, 1+y); + setPrintPos (1, 1+y); print (blank); } diff --git a/src/fbuttongroup.h b/src/fbuttongroup.h index f6303cd0..a05aea5c 100644 --- a/src/fbuttongroup.h +++ b/src/fbuttongroup.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fcheckbox.cpp b/src/fcheckbox.cpp index b0ed2d4a..03c2d1d0 100644 --- a/src/fcheckbox.cpp +++ b/src/fcheckbox.cpp @@ -53,7 +53,7 @@ void FCheckBox::drawCheckButton() if ( ! isVisible() ) return; - printPos (1,1); + setPrintPos (1,1); setColor(); if ( isMonochron() ) diff --git a/src/fcheckbox.h b/src/fcheckbox.h index 98f1cb5c..a52890d6 100644 --- a/src/fcheckbox.h +++ b/src/fcheckbox.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fcheckmenuitem.h b/src/fcheckmenuitem.h index 330f2225..36b3870e 100644 --- a/src/fcheckmenuitem.h +++ b/src/fcheckmenuitem.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fdialog.cpp b/src/fdialog.cpp index ece9bfef..76dde87e 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -163,22 +163,22 @@ void FDialog::drawBorder() { for (int y=y1; y < y2; y++) { - printPos (x1, y); + setPrintPos (x1, y); // border left ⎸ print (fc::NF_border_line_left); - printPos (x2, y); + setPrintPos (x2, y); // border right⎹ print (fc::NF_rev_border_line_right); } - printPos (x1, y2); + setPrintPos (x1, y2); // lower left corner border ⎣ print (fc::NF_border_corner_lower_left); for (int x=1; x < getWidth()-1; x++) // low line _ print (fc::NF_border_line_bottom); - printPos (x2, y2); + setPrintPos (x2, y2); // lower right corner border ⎦ print (fc::NF_rev_border_corner_lower_right); } @@ -195,7 +195,7 @@ void FDialog::drawTitleBar() const int menu_btn = 3; // draw the title button - printPos (1, 1); + setPrintPos (1, 1); if ( dialog_menu && dialog_menu->isVisible() ) setColor (wc.titlebar_button_focus_fg, wc.titlebar_button_focus_bg); @@ -204,7 +204,7 @@ void FDialog::drawTitleBar() if ( isMonochron() ) { - if ( isActiveWindow() ) + if ( isWindowActive() ) setReverse(false); else setReverse(true); @@ -244,7 +244,7 @@ void FDialog::drawTitleBar() if ( getMaxColor() < 16 ) setBold(); - if ( isActiveWindow() || (dialog_menu && dialog_menu->isVisible()) ) + if ( isWindowActive() || (dialog_menu && dialog_menu->isVisible()) ) setColor (wc.titlebar_active_fg, wc.titlebar_active_bg); else setColor (wc.titlebar_inactive_fg, wc.titlebar_inactive_bg); @@ -352,7 +352,7 @@ void FDialog::drawTitleBar() setReverse(false); /* print the number of window in stack */ -//printPos (getWidth()-2, 1); +//setPrintPos (getWidth()-2, 1); //printf ("(%d)", getWindowLayer(this)); } @@ -538,7 +538,7 @@ void FDialog::drawDialogShadow() return; drawShadow(); - printPos (1, 1+getHeight()); + setPrintPos (1, 1+getHeight()); setTransparent(); print(' '); unsetTransparent(); @@ -757,7 +757,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) has_raised = raiseWindow(); - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) activateDialog(); if ( has_raised ) @@ -815,7 +815,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) // click on titlebar: just activate if ( mouse_x >= 4 && mouse_x <= getWidth() && mouse_y == 1 ) { - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) activateDialog(); } } @@ -827,7 +827,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) { bool has_lowered = lowerWindow(); - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) activateDialog(); else if ( has_lowered ) updateTerminal(); @@ -1077,7 +1077,7 @@ void FDialog::onMouseDoubleClick (FMouseEvent* ev) //---------------------------------------------------------------------- void FDialog::onAccel (FAccelEvent*) { - if ( ! (isHiddenWindow() || isActiveWindow()) ) + if ( ! (isWindowHidden() || isWindowActive()) ) { bool has_raised = raiseWindow(); activateDialog(); diff --git a/src/fdialog.h b/src/fdialog.h index 6cf74713..64beee8a 100644 --- a/src/fdialog.h +++ b/src/fdialog.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fdialoglistmenu.h b/src/fdialoglistmenu.h index 17efb6f0..1a69ceb5 100644 --- a/src/fdialoglistmenu.h +++ b/src/fdialoglistmenu.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fenum.h b/src/fenum.h index b552d6d3..6c752309 100644 --- a/src/fenum.h +++ b/src/fenum.h @@ -967,6 +967,87 @@ class fc CurlyBrackets = 3, // { } AngleBrackets = 4 // < > }; + + enum termcaps + { + t_bell, + t_clear_screen, + t_cursor_home, + t_cursor_to_ll, + t_carriage_return, + t_tab, + t_back_tab, + t_insert_padding, + t_insert_character, + t_parm_ich, + t_initialize_color, + t_initialize_pair, + t_set_a_foreground, + t_set_a_background, + t_set_foreground, + t_set_background, + t_set_color_pair, + t_orig_pair, + t_orig_colors, + t_no_color_video, + t_cursor_address, + t_column_address, + t_row_address, + t_cursor_visible, + t_cursor_invisible, + t_cursor_normal, + t_cursor_up, + t_cursor_down, + t_cursor_left, + t_cursor_right, + t_parm_up_cursor, + t_parm_down_cursor, + t_parm_left_cursor, + 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, + t_enter_bold_mode, + t_exit_bold_mode, + t_enter_dim_mode, + t_exit_dim_mode, + t_enter_italics_mode, + t_exit_italics_mode, + t_enter_underline_mode, + t_exit_underline_mode, + t_enter_blink_mode, + t_exit_blink_mode, + t_enter_reverse_mode, + t_exit_reverse_mode, + t_enter_standout_mode, + t_exit_standout_mode, + t_enter_secure_mode, + t_exit_secure_mode, + t_enter_protected_mode, + t_exit_protected_mode, + t_enter_crossed_out_mode, + t_exit_crossed_out_mode, + t_enter_dbl_underline_mode, + t_exit_dbl_underline_mode, + t_set_attributes, + t_exit_attribute_mode, + t_enter_alt_charset_mode, + t_exit_alt_charset_mode, + t_enter_pc_charset_mode, + t_exit_pc_charset_mode, + t_enter_insert_mode, + t_exit_insert_mode, + t_enter_am_mode, + t_exit_am_mode, + t_acs_chars, + t_keypad_xmit, + t_keypad_local, + t_key_mouse + }; }; #pragma pack(pop) diff --git a/src/ffiledialog.h b/src/ffiledialog.h index 84b6dadd..0fc00e82 100644 --- a/src/ffiledialog.h +++ b/src/ffiledialog.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/flabel.cpp b/src/flabel.cpp index 6ec3db69..2ec4dadf 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -284,7 +284,7 @@ void FLabel::draw() else std::wcsncpy(dest, src, length); - printPos (1, 1+int(y)); + setPrintPos (1, 1+int(y)); if ( hotkeypos != -1 ) { @@ -314,7 +314,7 @@ void FLabel::draw() if ( hotkeypos != -1 ) length--; - printPos (1,1); + setPrintPos (1,1); xoffset = getXOffset (int(length)); printLine (LabelText, length, hotkeypos, xoffset); delete[] LabelText; @@ -363,7 +363,7 @@ void FLabel::hide() blank = new char[size+1]; std::memset(blank, ' ', uLong(size)); blank[getWidth()] = '\0'; - printPos (1,1); + setPrintPos (1,1); print (blank); delete[] blank; } diff --git a/src/flabel.h b/src/flabel.h index a43c2db5..e50d7fd0 100644 --- a/src/flabel.h +++ b/src/flabel.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/flineedit.cpp b/src/flineedit.cpp index a01c2911..f661d8fb 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -53,7 +53,7 @@ FLineEdit::~FLineEdit() // destructor { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); @@ -134,7 +134,7 @@ void FLineEdit::drawInputField() isShadow = ((flags & fc::shadow) != 0 ); updateVTerm(false); - printPos (1, 1); + setPrintPos (1, 1); if ( isMonochron() ) { @@ -310,7 +310,7 @@ void FLineEdit::hide() for (int y=0; y < getHeight()+s; y++) { - printPos (1, 1+y); + setPrintPos (1, 1+y); print (blank); } @@ -490,7 +490,7 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); @@ -499,7 +499,7 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) { setXTermCursorStyle(fc::steady_block); setKDECursor(fc::BlockCursor); - setConsoleCursor(fc::full_block_cursor); + setConsoleCursor(fc::full_block_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:eeee/0000/0000"); @@ -769,7 +769,7 @@ void FLineEdit::onHide (FHideEvent*) { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } @@ -782,7 +782,7 @@ void FLineEdit::onFocusIn (FFocusEvent*) { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } @@ -790,7 +790,7 @@ void FLineEdit::onFocusIn (FFocusEvent*) { setXTermCursorStyle(fc::steady_block); setKDECursor(fc::BlockCursor); - setConsoleCursor(fc::full_block_cursor); + setConsoleCursor(fc::full_block_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:0000/0000/0000"); } @@ -816,7 +816,7 @@ void FLineEdit::onFocusOut (FFocusEvent*) { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, isCursorHidden()); if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); diff --git a/src/flineedit.h b/src/flineedit.h index 123ead66..50882bae 100644 --- a/src/flineedit.h +++ b/src/flineedit.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/flistbox.cpp b/src/flistbox.cpp index efd9bee8..5dba0eb9 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -151,7 +151,7 @@ void FListBox::draw() for (int y=2; y < getHeight(); y++) { - printPos (getWidth(),y); + setPrintPos (getWidth(),y); print (' '); // clear right side of the scrollbar } } @@ -196,7 +196,7 @@ void FListBox::drawLabel() txt = " " + text + " "; length = txt.getLength(); - printPos (2, 1); + setPrintPos (2, 1); if ( isEnabled() ) setColor(wc.label_emphasis_fg, wc.label_bg); @@ -246,7 +246,7 @@ void FListBox::drawList() for (uInt y=start; y < end; y++) { - printPos (2, 2 + int(y)); + setPrintPos (2, 2 + int(y)); bool serach_mark = false; bool lineHasBrackets = hasBrackets(int(y) + yoffset + 1); bool isLineSelected = isSelected(int(y) + yoffset + 1); @@ -599,7 +599,7 @@ void FListBox::hide() for (int y=0; y < getHeight(); y++) { - printPos (1, 1 + y); + setPrintPos (1, 1 + y); print (blank); } @@ -1792,7 +1792,7 @@ void FListBox::clear() for (int y=0; y < getHeight()-2; y++) { - printPos (2, 2 + y); + setPrintPos (2, 2 + y); print (blank); } diff --git a/src/flistbox.h b/src/flistbox.h index 960b1157..6ca59ab7 100644 --- a/src/flistbox.h +++ b/src/flistbox.h @@ -12,6 +12,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fmenu.cpp b/src/fmenu.cpp index f752ed5f..5584bf3d 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -595,28 +595,27 @@ void FMenu::drawItems() while ( iter != end ) { - wchar_t* src; - wchar_t* dest; - wchar_t* item_text; - FString txt; - uInt txt_length; - int hotkeypos, to_char; - int accel_key = (*iter)->accel_key; - bool has_menu = (*iter)->hasMenu(); - bool is_enabled = (*iter)->isEnabled(); - bool is_checked = (*iter)->isChecked(); - bool is_checkable = (*iter)->checkable; - bool is_radio_btn = (*iter)->radio_button; - bool is_selected = (*iter)->isSelected(); - bool is_noUnderline = (((*iter)->getFlags() & fc::no_underline) != 0); - bool is_separator = (*iter)->isSeparator(); - - if ( is_separator ) + if ( (*iter)->isSeparator() ) { drawSeparator(y); } else { + wchar_t* src; + wchar_t* dest; + wchar_t* item_text; + FString txt; + uInt txt_length; + int hotkeypos, to_char; + int accel_key = (*iter)->accel_key; + bool has_menu = (*iter)->hasMenu(); + bool is_enabled = (*iter)->isEnabled(); + bool is_checked = (*iter)->isChecked(); + bool is_checkable = (*iter)->checkable; + bool is_radio_btn = (*iter)->radio_button; + bool is_selected = (*iter)->isSelected(); + bool is_noUnderline = (((*iter)->getFlags() & fc::no_underline) != 0); + if ( is_enabled ) { if ( is_selected ) @@ -645,7 +644,7 @@ void FMenu::drawItems() setReverse(true); } - printPos (2, 2 + y); + setPrintPos (2, 2 + y); setColor(); if ( has_checkable_items ) @@ -799,7 +798,7 @@ void FMenu::drawItems() //---------------------------------------------------------------------- inline void FMenu::drawSeparator(int y) { - printPos (1, 2 + y); + setPrintPos (1, 2 + y); setColor (wc.menu_active_fg, wc.menu_active_bg); if ( isMonochron() ) @@ -1001,7 +1000,7 @@ void FMenu::onMouseDown (FMouseEvent* ev) if ( mouse_down ) return; - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) setActiveWindow(this); mouse_down = true; @@ -1190,7 +1189,7 @@ void FMenu::onMouseMove (FMouseEvent* ev) if ( ev->getButton() != fc::LeftButton ) return; - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) setActiveWindow(this); if ( mouse_down && ! item_list.empty() ) diff --git a/src/fmenu.h b/src/fmenu.h index 8ec25aea..91335759 100644 --- a/src/fmenu.h +++ b/src/fmenu.h @@ -8,8 +8,13 @@ // ▕ FObject ▏ ▕ FTerm ▏ // ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ // ▲ ▲ -// │ │ *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ -// └─────┬─────┘ ┌ - -▕ FRadioMenuItem ▏ +// │ │ +// └─────┬─────┘ +// │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ +// ▲ ┌ - -▕ FRadioMenuItem ▏ // │ : ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ // ▕▔▔▔▔▔▔▔▔▔▏ : // ▕ FWidget ▏ : *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index 79ae6f9b..f9e86fc6 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -314,7 +314,7 @@ void FMenuBar::drawItems() return; updateVTerm(false); - printPos (1,1); + setPrintPos (1,1); if ( isMonochron() ) setReverse(true); @@ -424,12 +424,12 @@ void FMenuBar::drawItems() { if ( startpos < screenWidth ) { - printPos (screenWidth - 1, 1); + setPrintPos (screenWidth - 1, 1); print (".."); } else if ( startpos-1 <= screenWidth ) { - printPos (screenWidth, 1); + setPrintPos (screenWidth, 1); print (' '); } } @@ -596,7 +596,7 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) mouse_down = true; - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) setActiveWindow(this); if ( ! item_list.empty() ) @@ -769,7 +769,7 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) if ( ev->getButton() != fc::LeftButton ) return; - if ( ! isActiveWindow() ) + if ( ! isWindowActive() ) setActiveWindow(this); if ( mouse_down && ! item_list.empty() ) @@ -911,7 +911,7 @@ void FMenuBar::hide() blank = new char[screenWidth+1]; std::memset(blank, ' ', uLong(screenWidth)); blank[screenWidth] = '\0'; - printPos (1,1); + setPrintPos (1,1); print (blank); delete[] blank; } diff --git a/src/fmenubar.h b/src/fmenubar.h index 0d720db2..8bcd807d 100644 --- a/src/fmenubar.h +++ b/src/fmenubar.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index e0af3dd1..c1efd91f 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -853,32 +853,32 @@ void FMenuItem::openMenu() FMenu* dd_menu; // Drop-down menu FMenu* open_menu; - if ( hasMenu() ) + if ( ! hasMenu() ) + return; + + dd_menu = getMenu(); // Drop-down menu + + if ( dd_menu->isVisible() ) + return; + + open_menu = static_cast(getOpenMenu()); + + if ( open_menu && open_menu != dd_menu ) { - dd_menu = getMenu(); - - if ( dd_menu->isVisible() ) - return; - - open_menu = static_cast(getOpenMenu()); - - if ( open_menu && open_menu != dd_menu ) - { - open_menu->hide(); - open_menu->hideSubMenus(); - } - - if ( dialog_index ) - createDialogList (dd_menu); - - setOpenMenu(dd_menu); - dd_menu->setVisible(); - dd_menu->show(); - dd_menu->raiseWindow(dd_menu); - dd_menu->redraw(); - updateTerminal(); - flush_out(); + open_menu->hide(); + open_menu->hideSubMenus(); } + + if ( dialog_index ) + createDialogList (dd_menu); + + setOpenMenu(dd_menu); + dd_menu->setVisible(); + dd_menu->show(); + dd_menu->raiseWindow(dd_menu); + dd_menu->redraw(); + updateTerminal(); + flush_out(); } //---------------------------------------------------------------------- diff --git a/src/fmenuitem.h b/src/fmenuitem.h index ca4da3a2..355dd823 100644 --- a/src/fmenuitem.h +++ b/src/fmenuitem.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fmessagebox.cpp b/src/fmessagebox.cpp index c82207a2..535a4b51 100644 --- a/src/fmessagebox.cpp +++ b/src/fmessagebox.cpp @@ -245,7 +245,7 @@ void FMessageBox::draw() if ( center_text ) // center one line center_x = int((max_line_width - headline_length) / 2); - printPos (1 + msg_x + center_x, 4); + setPrintPos (1 + msg_x + center_x, 4); print (headline_text); head_offset = 2; } @@ -259,7 +259,7 @@ void FMessageBox::draw() if ( center_text ) // center one line center_x = int((max_line_width - line_length) / 2); - printPos (1 + msg_x + center_x, 4 + head_offset + i); + setPrintPos (1 + msg_x + center_x, 4 + head_offset + i); print(text_components[i]); } diff --git a/src/fmessagebox.h b/src/fmessagebox.h index f0b253ba..b766d379 100644 --- a/src/fmessagebox.h +++ b/src/fmessagebox.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/foptimove.cpp b/src/foptimove.cpp index d2d0f897..88413ee8 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -562,7 +562,7 @@ inline bool FOptiMove::isWideMove ( int xold, int yold } //---------------------------------------------------------------------- -char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) +char* FOptiMove::moveCursor (int xold, int yold, int xnew, int ynew) { char null_result[sizeof(move_buf)]; char* null_ptr = null_result; diff --git a/src/foptimove.h b/src/foptimove.h index e00891a8..28865aad 100644 --- a/src/foptimove.h +++ b/src/foptimove.h @@ -112,8 +112,8 @@ class FOptiMove void set_auto_left_margin (bool&); void set_eat_newline_glitch (bool&); - char* cursor_move (int, int, int, int); - void printDurations(); + char* moveCursor (int, int, int, int); + void printDurations(); }; #pragma pack(pop) diff --git a/src/fprogressbar.cpp b/src/fprogressbar.cpp index 87b8b233..fc4cf19b 100644 --- a/src/fprogressbar.cpp +++ b/src/fprogressbar.cpp @@ -37,7 +37,7 @@ void FProgressbar::drawPercentage() if ( isMonochron() ) setReverse(true); - printPos (getWidth() - 3, 0); + setPrintPos (getWidth() - 3, 0); if ( percentage < 0 || percentage > 100 ) print ("--- %"); @@ -53,7 +53,7 @@ void FProgressbar::drawBar() { int i = 1; float length = float(bar_length * percentage) / 100; - printPos (1,1); + setPrintPos (1,1); if ( isMonochron() ) { @@ -206,12 +206,12 @@ void FProgressbar::hide() for (int y=0; y < getHeight()+s; y++) { - printPos (1, 1 + y); + setPrintPos (1, 1 + y); print (blank); } delete[] blank; - printPos (getWidth() - 4, 0); + setPrintPos (getWidth() - 4, 0); print (" "); // hide percentage } diff --git a/src/fprogressbar.h b/src/fprogressbar.h index 687bcf57..76e6fc65 100644 --- a/src/fprogressbar.h +++ b/src/fprogressbar.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fradiobutton.cpp b/src/fradiobutton.cpp index c2b76180..b66811a2 100644 --- a/src/fradiobutton.cpp +++ b/src/fradiobutton.cpp @@ -54,7 +54,7 @@ void FRadioButton::drawRadioButton() if ( ! isVisible() ) return; - printPos (1,1); + setPrintPos (1,1); setColor(); if ( isMonochron() ) diff --git a/src/fradiobutton.h b/src/fradiobutton.h index d3902c54..27fee95a 100644 --- a/src/fradiobutton.h +++ b/src/fradiobutton.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fradiomenuitem.h b/src/fradiomenuitem.h index 2ea069ec..6f898e1b 100644 --- a/src/fradiomenuitem.h +++ b/src/fradiomenuitem.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fscrollbar.cpp b/src/fscrollbar.cpp index 30ef9d1d..f7726d3a 100644 --- a/src/fscrollbar.cpp +++ b/src/fscrollbar.cpp @@ -571,7 +571,7 @@ void FScrollbar::drawBar() for (z=1; z <= slider_pos; z++) { - printPos (1, 1 + z); + setPrintPos (1, 1 + z); if ( isNewFont() ) print (fc::NF_border_line_left); // ⎸ @@ -589,7 +589,7 @@ void FScrollbar::drawBar() for (z=1; z <= slider_length; z++) { - printPos (1, 1 + slider_pos + z); + setPrintPos (1, 1 + slider_pos + z); if ( isNewFont() ) print (' '); @@ -604,7 +604,7 @@ void FScrollbar::drawBar() for (z=slider_pos+slider_length+1; z <= bar_length; z++) { - printPos (1, 1 + z); + setPrintPos (1, 1 + z); if ( isNewFont() ) print (fc::NF_border_line_left); // ⎸ @@ -621,9 +621,9 @@ void FScrollbar::drawBar() z = 0; if ( isNewFont() ) - printPos (3 + z, 1); + setPrintPos (3 + z, 1); else - printPos (2 + z, 1); + setPrintPos (2 + z, 1); for (; z < slider_pos; z++) { @@ -678,13 +678,13 @@ void FScrollbar::drawButtons() if ( isNewFont() ) { - printPos (1,1); + setPrintPos (1,1); if ( bar_orientation == fc::vertical ) { print (fc::NF_rev_up_arrow1); print (fc::NF_rev_up_arrow2); - printPos (1, length); + setPrintPos (1, length); print (fc::NF_rev_down_arrow1); print (fc::NF_rev_down_arrow2); } @@ -692,14 +692,14 @@ void FScrollbar::drawButtons() { print (fc::NF_rev_left_arrow1); print (fc::NF_rev_left_arrow2); - printPos (length-1, 1); + setPrintPos (length-1, 1); print (fc::NF_rev_right_arrow1); print (fc::NF_rev_right_arrow2); } } else { - printPos (1,1); + setPrintPos (1,1); if ( isMonochron() ) setReverse(true); @@ -711,7 +711,7 @@ void FScrollbar::drawButtons() else print (fc::BlackUpPointingTriangle); // ▲ - printPos (1, length); + setPrintPos (1, length); if ( isCygwinTerminal() ) print ('v'); @@ -721,7 +721,7 @@ void FScrollbar::drawButtons() else // horizontal { print (fc::BlackLeftPointingPointer); // ◄ - printPos (length, 1); + setPrintPos (length, 1); print (fc::BlackRightPointingPointer); // ► } diff --git a/src/fscrollbar.h b/src/fscrollbar.h index c6677458..680d561b 100644 --- a/src/fscrollbar.h +++ b/src/fscrollbar.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fstatusbar.cpp b/src/fstatusbar.cpp index 9c59b0ff..a03f30c1 100644 --- a/src/fstatusbar.cpp +++ b/src/fstatusbar.cpp @@ -221,7 +221,7 @@ void FStatusBar::drawKeys() } updateVTerm(false); - printPos (1, 1); + setPrintPos (1, 1); if ( isMonochron() ) setReverse(true); @@ -356,7 +356,7 @@ void FStatusBar::hide() blank = new char[screenWidth+1]; std::memset(blank, ' ', uLong(screenWidth)); blank[screenWidth] = '\0'; - printPos (1, 1); + setPrintPos (1, 1); print (blank); delete[] blank; } @@ -583,7 +583,7 @@ void FStatusBar::drawMessage() updateVTerm(false); setColor (wc.statusbar_fg, wc.statusbar_bg); - printPos (x, 1); + setPrintPos (x, 1); if ( isMonochron() ) setReverse(true); diff --git a/src/fstatusbar.h b/src/fstatusbar.h index 35299fda..7a78411b 100644 --- a/src/fstatusbar.h +++ b/src/fstatusbar.h @@ -12,6 +12,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fswitch.cpp b/src/fswitch.cpp index 24cc8d06..974710f1 100644 --- a/src/fswitch.cpp +++ b/src/fswitch.cpp @@ -54,7 +54,7 @@ void FSwitch::drawCheckButton() wchar_t on[6] = L" On "; wchar_t off[6] = L" Off "; - printPos (1 + switch_offset_pos, 1); + setPrintPos (1 + switch_offset_pos, 1); if ( checked ) { diff --git a/src/fswitch.h b/src/fswitch.h index 4fc3f8e1..86eac5a0 100644 --- a/src/fswitch.h +++ b/src/fswitch.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/ftcap_map.h b/src/ftcap_map.h index c325b2a9..a4bef448 100644 --- a/src/ftcap_map.h +++ b/src/ftcap_map.h @@ -3,20 +3,9 @@ #ifndef _FTCAPMAP_H #define _FTCAPMAP_H -#pragma pack(push) -#pragma pack(1) +#include "ftermcap.h" -typedef struct -{ - char* string; - char tname[3]; -} -tcap_map; - -#pragma pack(pop) - - -static tcap_map tcap[] = +static FTermcap::tcap_map term_caps[] = { // .------------- term string // | .-------- Tcap-code @@ -115,85 +104,4 @@ static tcap_map tcap[] = * "XX", "Us" and "Ue" are unofficial and they are only used here. */ -enum termcaps -{ - t_bell, - t_clear_screen, - t_cursor_home, - t_cursor_to_ll, - t_carriage_return, - t_tab, - t_back_tab, - t_insert_padding, - t_insert_character, - t_parm_ich, - t_initialize_color, - t_initialize_pair, - t_set_a_foreground, - t_set_a_background, - t_set_foreground, - t_set_background, - t_set_color_pair, - t_orig_pair, - t_orig_colors, - t_no_color_video, - t_cursor_address, - t_column_address, - t_row_address, - t_cursor_visible, - t_cursor_invisible, - t_cursor_normal, - t_cursor_up, - t_cursor_down, - t_cursor_left, - t_cursor_right, - t_parm_up_cursor, - t_parm_down_cursor, - t_parm_left_cursor, - 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, - t_enter_bold_mode, - t_exit_bold_mode, - t_enter_dim_mode, - t_exit_dim_mode, - t_enter_italics_mode, - t_exit_italics_mode, - t_enter_underline_mode, - t_exit_underline_mode, - t_enter_blink_mode, - t_exit_blink_mode, - t_enter_reverse_mode, - t_exit_reverse_mode, - t_enter_standout_mode, - t_exit_standout_mode, - t_enter_secure_mode, - t_exit_secure_mode, - t_enter_protected_mode, - t_exit_protected_mode, - t_enter_crossed_out_mode, - t_exit_crossed_out_mode, - t_enter_dbl_underline_mode, - t_exit_dbl_underline_mode, - t_set_attributes, - t_exit_attribute_mode, - t_enter_alt_charset_mode, - t_exit_alt_charset_mode, - t_enter_pc_charset_mode, - t_exit_pc_charset_mode, - t_enter_insert_mode, - t_exit_insert_mode, - t_enter_am_mode, - t_exit_am_mode, - t_acs_chars, - t_keypad_xmit, - t_keypad_local, - t_key_mouse -}; - #endif // _FTCAPMAP_H diff --git a/src/fterm.cpp b/src/fterm.cpp index 03f838bf..f810ca93 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -1,20 +1,17 @@ // File: fterm.cpp // Provides: class FTerm -#include "fapp.h" +#include "fterm.h" #include "fcharmap.h" #include "fkey_map.h" #include "ftcap_map.h" -#include "fterm.h" -#include "fwidget.h" -#include "fwindow.h" #include "fonts/newfont.h" #include "fonts/unicodemap.h" #include "fonts/vgafont.h" // global FTerm object -static FTerm* term_object = 0; +static FTerm* init_term_object = 0; // global init state static bool term_initialized = false; @@ -32,12 +29,9 @@ uInt FTerm::baudrate; uInt FTerm::tabstop; uInt FTerm::attr_without_color; bool FTerm::resize_term; -bool FTerm::hidden_cursor; bool FTerm::mouse_support; bool FTerm::raw_mode; bool FTerm::input_data_pending; -bool FTerm::terminal_update_pending; -bool FTerm::force_terminal_update; bool FTerm::non_blocking_stdin; bool FTerm::gpm_mouse_enabled; bool FTerm::color256; @@ -61,9 +55,6 @@ bool FTerm::mintty_terminal; bool FTerm::linux_terminal; bool FTerm::screen_terminal; bool FTerm::tmux_terminal; -bool FTerm::terminal_updates; -bool FTerm::stop_terminal_updates; -bool FTerm::vterm_updates; bool FTerm::pc_charset_console; bool FTerm::utf8_input; bool FTerm::utf8_state; @@ -78,14 +69,11 @@ bool FTerm::cursor_optimisation; bool FTerm::osc_support; uChar FTerm::x11_button_state; termios FTerm::term_init; - char FTerm::termtype[30] = ""; char* FTerm::term_name = 0; char* FTerm::locale_name = 0; char* FTerm::locale_xterm = 0; -FPoint* FTerm::term_pos = 0; FPoint* FTerm::mouse = 0; -FPoint* FTerm::cursor = 0; FRect* FTerm::term = 0; char FTerm::exit_message[8192] = ""; @@ -97,16 +85,11 @@ const FString* FTerm::sec_da = 0; FOptiMove* FTerm::opti_move = 0; FOptiAttr* FTerm::opti_attr = 0; FTerm::modifier_key FTerm::mod_key; -FTerm::term_area* FTerm::vterm = 0; -FTerm::term_area* FTerm::vdesktop = 0; -FTerm::term_area* FTerm::last_area = 0; -FTerm::term_area* FTerm::active_area = 0; -std::queue* FTerm::output_buffer = 0; std::map* FTerm::vt100_alt_char = 0; std::map* \ FTerm::encoding_set = 0; -FOptiAttr::char_data FTerm::term_attribute; -FOptiAttr::char_data FTerm::next_attribute; +FTermcap::tcap_map* FTermcap::tcap = 0; +FTermcap::tcap_map* FTerm::tcap = term_caps; console_font_op FTerm::screen_font; unimapdesc FTerm::screen_unicode_map; fc::consoleCursorStyle FTerm::console_cursor_style; @@ -120,26 +103,9 @@ fc::consoleCursorStyle FTerm::console_cursor_style; //---------------------------------------------------------------------- FTerm::FTerm() : map() - , vwin(0) { - terminal_updates = false; - vterm_updates = true; - if ( ! term_initialized ) { - term_initialized = true; - term_object = this; - fd_tty = -1; - vterm = 0; - vdesktop = 0; - last_area = 0; - opti_move = new FOptiMove(); - opti_attr = new FOptiAttr(); - term = new FRect(0,0,0,0); - term_pos = new FPoint(-1,-1); - mouse = new FPoint(0,0); - cursor = new FPoint(0,0); - init(); } } @@ -147,15 +113,9 @@ FTerm::FTerm() //---------------------------------------------------------------------- FTerm::~FTerm() // destructor { - if ( term_object == this ) + if ( init_term_object == this ) { - this->finish(); - delete cursor; - delete mouse; - delete term_pos; - delete term; - delete opti_attr; - delete opti_move; + finish(); if ( exit_message[0] ) { @@ -523,9 +483,12 @@ int FTerm::setUnicodeMap (struct unimapdesc* unimap) } //---------------------------------------------------------------------- -int FTerm::setLightBackgroundColors (bool on) +int FTerm::setBlinkAsIntensity (bool on) { - if ( getuid() != 0 ) + // Uses blink-bit as background intensity. + // That permits 16 colors for background + + if ( getuid() != 0 ) // Direct hardware access requires root privileges return -2; if ( fd_tty < 0 ) @@ -687,6 +650,30 @@ int FTerm::parseKeyString ( char* buffer return int(key == 127 ? fc::Fkey_backspace : key); } +//---------------------------------------------------------------------- +bool& FTerm::unprocessedInput() +{ + return input_data_pending; +} + +//---------------------------------------------------------------------- +int FTerm::getLineNumber() +{ + if ( term->getHeight() == 0 ) + getTermSize(); + + return term->getHeight(); +} + +//---------------------------------------------------------------------- +int FTerm::getColumnNumber() +{ + if ( term->getWidth() == 0 ) + getTermSize(); + + return term->getWidth(); +} + //---------------------------------------------------------------------- FString FTerm::getKeyName (int keynum) { @@ -818,7 +805,7 @@ void FTerm::signal_handler (int signum) case SIGABRT: case SIGILL: case SIGSEGV: - term_object->finish(); + init_term_object->finish(); std::fflush (stderr); std::fflush (stdout); std::fprintf ( stderr @@ -1004,14 +991,14 @@ char* FTerm::parseSecDA (char*& current_termtype) switch ( terminal_id_type ) { - case 0: + case 0: // DEC VT100 if ( terminal_id_version == 115 ) kde_konsole = true; else if ( terminal_id_version == 136 ) putty_terminal = true; // PuTTY break; - case 1: + case 1: // DEC VT220 if ( ! sec_da_supported ) { if ( terminal_id_version == 2 ) // also used by apple terminal @@ -1026,6 +1013,16 @@ char* FTerm::parseSecDA (char*& current_termtype) } break; + case 2: // DEC VT240 + case 18: // DEC VT330 + case 19: // DEC VT340 + case 24: // DEC VT320 + case 41: // DEC VT420 + case 61: // DEC VT510 + case 64: // DEC VT520 + case 65: // DEC VT525 + break; + case 32: // Tera Term tera_terminal = true; new_termtype = const_cast("teraterm"); @@ -1034,7 +1031,7 @@ char* FTerm::parseSecDA (char*& current_termtype) case 77: // mintty mintty_terminal = true; new_termtype = const_cast("xterm-256color"); - // application escape key mode + // switch to application escape key mode putstring (CSI "?7727h"); std::fflush(stdout); break; @@ -1104,13 +1101,13 @@ void FTerm::oscPostfix() void FTerm::init_alt_charset() { // read the used vt100 pairs - if ( tcap[t_acs_chars].string ) + if ( tcap[fc::t_acs_chars].string ) { - for (int n=0; tcap[t_acs_chars].string[n]; tcap[t_acs_chars].string += 2) + for (int n=0; tcap[fc::t_acs_chars].string[n]; tcap[fc::t_acs_chars].string += 2) { // insert the vt100 key/value pairs into a map - uChar p1 = uChar(tcap[t_acs_chars].string[n]); - uChar p2 = uChar(tcap[t_acs_chars].string[n+1]); + uChar p1 = uChar(tcap[fc::t_acs_chars].string[n]); + uChar p2 = uChar(tcap[fc::t_acs_chars].string[n+1]); (*vt100_alt_char)[p1] = p2; } } @@ -1156,42 +1153,42 @@ void FTerm::init_pc_charset() if ( gnome_terminal || linux_terminal ) { // fallback if tcap "S2" is not found - if ( ! tcap[t_enter_pc_charset_mode].string ) + if ( ! tcap[fc::t_enter_pc_charset_mode].string ) { if ( utf8_console ) { // Select iso8859-1 + null mapping - tcap[t_enter_pc_charset_mode].string = \ + tcap[fc::t_enter_pc_charset_mode].string = \ const_cast(ESC "%@" ESC "(U"); } else { // Select null mapping - tcap[t_enter_pc_charset_mode].string = \ + tcap[fc::t_enter_pc_charset_mode].string = \ const_cast(ESC "(U"); } - opti_attr->set_enter_pc_charset_mode (tcap[t_enter_pc_charset_mode].string); + opti_attr->set_enter_pc_charset_mode (tcap[fc::t_enter_pc_charset_mode].string); reinit = true; } // fallback if tcap "S3" is not found - if ( ! tcap[t_exit_pc_charset_mode].string ) + if ( ! tcap[fc::t_exit_pc_charset_mode].string ) { if ( utf8_console ) { // Select ascii mapping + utf8 - tcap[t_exit_pc_charset_mode].string = \ + tcap[fc::t_exit_pc_charset_mode].string = \ const_cast(ESC "(B" ESC "%G"); } else { // Select ascii mapping - tcap[t_enter_pc_charset_mode].string = \ + tcap[fc::t_enter_pc_charset_mode].string = \ const_cast(ESC "(B"); } - opti_attr->set_exit_pc_charset_mode (tcap[t_exit_pc_charset_mode].string); + opti_attr->set_exit_pc_charset_mode (tcap[fc::t_exit_pc_charset_mode].string); reinit = true; } } @@ -1215,6 +1212,9 @@ void FTerm::init_termcaps() static char string_buf[2048]; char* buffer = string_buf; + // share the terminal capabilities + FTermcap().setTermcapMap(tcap); + // open the termcap file + load entry for termtype if ( tgetent(term_buffer, termtype) == 1 ) { @@ -1269,69 +1269,69 @@ void FTerm::init_termcaps() tcap[i].string = tgetstr(tcap[i].tname, &buffer); // set invisible cursor for cygwin terminal - if ( cygwin_terminal && ! tcap[t_cursor_invisible].string ) - tcap[t_cursor_invisible].string = \ + if ( cygwin_terminal && ! tcap[fc::t_cursor_invisible].string ) + tcap[fc::t_cursor_invisible].string = \ const_cast(CSI "?25l"); // set visible cursor for cygwin terminal - if ( cygwin_terminal && ! tcap[t_cursor_visible].string ) - tcap[t_cursor_visible].string = \ + if ( cygwin_terminal && ! tcap[fc::t_cursor_visible].string ) + tcap[fc::t_cursor_visible].string = \ const_cast(CSI "?25h"); // set ansi blink for cygwin terminal - if ( cygwin_terminal && ! tcap[t_enter_blink_mode].string ) - tcap[t_enter_blink_mode].string = \ + if ( cygwin_terminal && ! tcap[fc::t_enter_blink_mode].string ) + tcap[fc::t_enter_blink_mode].string = \ const_cast(CSI "5m"); // set enter/exit alternative charset mode for rxvt terminal if ( rxvt_terminal && std::strncmp(termtype, "rxvt-16color", 12) == 0 ) { - tcap[t_enter_alt_charset_mode].string = \ + tcap[fc::t_enter_alt_charset_mode].string = \ const_cast(ESC "(0"); - tcap[t_exit_alt_charset_mode].string = \ + tcap[fc::t_exit_alt_charset_mode].string = \ const_cast(ESC "(B"); } // set exit underline for gnome terminal if ( gnome_terminal ) - tcap[t_exit_underline_mode].string = \ + tcap[fc::t_exit_underline_mode].string = \ const_cast(CSI "24m"); // set ansi foreground and background color if ( linux_terminal || cygwin_terminal ) { - tcap[t_set_a_foreground].string = \ + tcap[fc::t_set_a_foreground].string = \ const_cast(CSI "3%p1%{8}%m%d%?%p1%{7}%>%t;1%e;21%;m"); - tcap[t_set_a_background].string = \ + tcap[fc::t_set_a_background].string = \ const_cast(CSI "4%p1%{8}%m%d%?%p1%{7}%>%t;5%e;25%;m"); - tcap[t_orig_pair].string = \ + tcap[fc::t_orig_pair].string = \ const_cast(CSI "39;49;25m"); } else if ( rxvt_terminal && ! urxvt_terminal ) { - tcap[t_set_a_foreground].string = \ + tcap[fc::t_set_a_foreground].string = \ const_cast(CSI "%?%p1%{8}%<%t%p1%{30}%+%e%p1%'R'%+%;%dm"); - tcap[t_set_a_background].string = \ + tcap[fc::t_set_a_background].string = \ const_cast(CSI "%?%p1%{8}%<%t%p1%'('%+%e%p1%{92}%+%;%dm"); } else if ( tera_terminal ) { - tcap[t_set_a_foreground].string = \ + tcap[fc::t_set_a_foreground].string = \ const_cast(CSI "38;5;%p1%dm"); - tcap[t_set_a_background].string = \ + tcap[fc::t_set_a_background].string = \ const_cast(CSI "48;5;%p1%dm"); - tcap[t_exit_attribute_mode].string = \ + tcap[fc::t_exit_attribute_mode].string = \ const_cast(CSI "0m" SI); } else if ( putty_terminal ) { - tcap[t_set_a_foreground].string = \ + tcap[fc::t_set_a_foreground].string = \ const_cast(CSI "%?%p1%{8}%<" "%t3%p1%d" "%e%p1%{16}%<" "%t9%p1%{8}%-%d" "%e38;5;%p1%d%;m"); - tcap[t_set_a_background].string = \ + tcap[fc::t_set_a_background].string = \ const_cast(CSI "%?%p1%{8}%<" "%t4%p1%d" "%e%p1%{16}%<" @@ -1340,23 +1340,23 @@ void FTerm::init_termcaps() } // fallback if "AF" is not found - if ( ! tcap[t_set_a_foreground].string ) - tcap[t_set_a_foreground].string = \ + if ( ! tcap[fc::t_set_a_foreground].string ) + tcap[fc::t_set_a_foreground].string = \ const_cast(CSI "3%p1%dm"); // fallback if "AB" is not found - if ( ! tcap[t_set_a_background].string ) - tcap[t_set_a_background].string = \ + if ( ! tcap[fc::t_set_a_background].string ) + tcap[fc::t_set_a_background].string = \ const_cast(CSI "4%p1%dm"); // fallback if "Ic" is not found - if ( ! tcap[t_initialize_color].string ) + if ( ! tcap[fc::t_initialize_color].string ) { if ( screen_terminal ) { if ( tmux_terminal ) { - tcap[t_initialize_color].string = \ + tcap[fc::t_initialize_color].string = \ const_cast(ESC "Ptmux;" ESC OSC "4;%p1%d;rgb:" "%p2%{255}%*%{1000}%/%2.2X/" "%p3%{255}%*%{1000}%/%2.2X/" @@ -1364,7 +1364,7 @@ void FTerm::init_termcaps() } else { - tcap[t_initialize_color].string = \ + tcap[fc::t_initialize_color].string = \ const_cast(ESC "P" OSC "4;%p1%d;rgb:" "%p2%{255}%*%{1000}%/%2.2X/" "%p3%{255}%*%{1000}%/%2.2X/" @@ -1373,7 +1373,7 @@ void FTerm::init_termcaps() } else { - tcap[t_initialize_color].string = \ + tcap[fc::t_initialize_color].string = \ const_cast(OSC "P%p1%x" "%p2%{255}%*%{1000}%/%02x" "%p3%{255}%*%{1000}%/%02x" @@ -1382,53 +1382,53 @@ void FTerm::init_termcaps() } // fallback if "ti" is not found - if ( ! tcap[t_enter_ca_mode].string ) - tcap[t_enter_ca_mode].string = \ + if ( ! tcap[fc::t_enter_ca_mode].string ) + tcap[fc::t_enter_ca_mode].string = \ const_cast(ESC "7" CSI "?47h"); // fallback if "te" is not found - if ( ! tcap[t_exit_ca_mode].string ) - tcap[t_exit_ca_mode].string = \ + if ( ! tcap[fc::t_exit_ca_mode].string ) + tcap[fc::t_exit_ca_mode].string = \ const_cast(CSI "?47l" ESC "8" CSI "m"); // set ansi move if "cm" is not found - if ( ! tcap[t_cursor_address].string ) - tcap[t_cursor_address].string = \ + if ( ! tcap[fc::t_cursor_address].string ) + tcap[fc::t_cursor_address].string = \ const_cast(CSI "%i%p1%d;%p2%dH"); // test for standard ECMA-48 (ANSI X3.64) terminal - if ( tcap[t_exit_underline_mode].string - && std::strncmp(tcap[t_exit_underline_mode].string, CSI "24m", 5) == 0 ) + if ( tcap[fc::t_exit_underline_mode].string + && std::strncmp(tcap[fc::t_exit_underline_mode].string, CSI "24m", 5) == 0 ) { // seems to be a ECMA-48 (ANSI X3.64) compatible terminal - tcap[t_enter_dbl_underline_mode].string = \ + tcap[fc::t_enter_dbl_underline_mode].string = \ const_cast(CSI "21m"); // Exit single underline, too - tcap[t_exit_dbl_underline_mode].string = \ + tcap[fc::t_exit_dbl_underline_mode].string = \ const_cast(CSI "24m"); - tcap[t_exit_bold_mode].string = \ + tcap[fc::t_exit_bold_mode].string = \ const_cast(CSI "22m"); // Exit dim, too - tcap[t_exit_dim_mode].string = \ + tcap[fc::t_exit_dim_mode].string = \ const_cast(CSI "22m"); - tcap[t_exit_underline_mode].string = \ + tcap[fc::t_exit_underline_mode].string = \ const_cast(CSI "24m"); - tcap[t_exit_blink_mode].string = \ + tcap[fc::t_exit_blink_mode].string = \ const_cast(CSI "25m"); - tcap[t_exit_reverse_mode].string = \ + tcap[fc::t_exit_reverse_mode].string = \ const_cast(CSI "27m"); - tcap[t_exit_secure_mode].string = \ + tcap[fc::t_exit_secure_mode].string = \ const_cast(CSI "28m"); - tcap[t_enter_crossed_out_mode].string = \ + tcap[fc::t_enter_crossed_out_mode].string = \ const_cast(CSI "9m"); - tcap[t_exit_crossed_out_mode].string = \ + tcap[fc::t_exit_crossed_out_mode].string = \ const_cast(CSI "29m"); } @@ -1467,8 +1467,8 @@ void FTerm::init_termcaps() key_up_string = tgetstr(const_cast("ku"), &buffer); if ( (key_up_string && (std::strcmp(key_up_string, CSI "A") == 0)) - || ( tcap[t_cursor_up].string - && (std::strcmp(tcap[t_cursor_up].string, CSI "A") == 0)) ) + || ( tcap[fc::t_cursor_up].string + && (std::strcmp(tcap[fc::t_cursor_up].string, CSI "A") == 0)) ) { for (int i=0; Fkey[i].tname[0] != 0; i++) { @@ -1509,63 +1509,63 @@ void FTerm::init_termcaps() // duration precalculation of the cursor movement strings opti_move->setTabStop(int(tabstop)); - opti_move->set_cursor_home (tcap[t_cursor_home].string); - opti_move->set_cursor_to_ll (tcap[t_cursor_to_ll].string); - opti_move->set_carriage_return (tcap[t_carriage_return].string); - opti_move->set_tabular (tcap[t_tab].string); - opti_move->set_back_tab (tcap[t_back_tab].string); - opti_move->set_cursor_up (tcap[t_cursor_up].string); - opti_move->set_cursor_down (tcap[t_cursor_down].string); - opti_move->set_cursor_left (tcap[t_cursor_left].string); - opti_move->set_cursor_right (tcap[t_cursor_right].string); - opti_move->set_cursor_address (tcap[t_cursor_address].string); - opti_move->set_column_address (tcap[t_column_address].string); - opti_move->set_row_address (tcap[t_row_address].string); - opti_move->set_parm_up_cursor (tcap[t_parm_up_cursor].string); - opti_move->set_parm_down_cursor (tcap[t_parm_down_cursor].string); - opti_move->set_parm_left_cursor (tcap[t_parm_left_cursor].string); - opti_move->set_parm_right_cursor (tcap[t_parm_right_cursor].string); + opti_move->set_cursor_home (tcap[fc::t_cursor_home].string); + opti_move->set_cursor_to_ll (tcap[fc::t_cursor_to_ll].string); + opti_move->set_carriage_return (tcap[fc::t_carriage_return].string); + opti_move->set_tabular (tcap[fc::t_tab].string); + opti_move->set_back_tab (tcap[fc::t_back_tab].string); + opti_move->set_cursor_up (tcap[fc::t_cursor_up].string); + opti_move->set_cursor_down (tcap[fc::t_cursor_down].string); + opti_move->set_cursor_left (tcap[fc::t_cursor_left].string); + opti_move->set_cursor_right (tcap[fc::t_cursor_right].string); + opti_move->set_cursor_address (tcap[fc::t_cursor_address].string); + opti_move->set_column_address (tcap[fc::t_column_address].string); + opti_move->set_row_address (tcap[fc::t_row_address].string); + opti_move->set_parm_up_cursor (tcap[fc::t_parm_up_cursor].string); + opti_move->set_parm_down_cursor (tcap[fc::t_parm_down_cursor].string); + opti_move->set_parm_left_cursor (tcap[fc::t_parm_left_cursor].string); + opti_move->set_parm_right_cursor (tcap[fc::t_parm_right_cursor].string); opti_move->set_auto_left_margin (automatic_left_margin); opti_move->set_eat_newline_glitch (eat_nl_glitch); //opti_move->printDurations(); // attribute settings opti_attr->setNoColorVideo (int(attr_without_color)); - opti_attr->set_enter_bold_mode (tcap[t_enter_bold_mode].string); - opti_attr->set_exit_bold_mode (tcap[t_exit_bold_mode].string); - opti_attr->set_enter_dim_mode (tcap[t_enter_dim_mode].string); - opti_attr->set_exit_dim_mode (tcap[t_exit_dim_mode].string); - opti_attr->set_enter_italics_mode (tcap[t_enter_italics_mode].string); - opti_attr->set_exit_italics_mode (tcap[t_exit_italics_mode].string); - opti_attr->set_enter_underline_mode (tcap[t_enter_underline_mode].string); - opti_attr->set_exit_underline_mode (tcap[t_exit_underline_mode].string); - opti_attr->set_enter_blink_mode (tcap[t_enter_blink_mode].string); - opti_attr->set_exit_blink_mode (tcap[t_exit_blink_mode].string); - opti_attr->set_enter_reverse_mode (tcap[t_enter_reverse_mode].string); - opti_attr->set_exit_reverse_mode (tcap[t_exit_reverse_mode].string); - opti_attr->set_enter_standout_mode (tcap[t_enter_standout_mode].string); - opti_attr->set_exit_standout_mode (tcap[t_exit_standout_mode].string); - opti_attr->set_enter_secure_mode (tcap[t_enter_secure_mode].string); - opti_attr->set_exit_secure_mode (tcap[t_exit_secure_mode].string); - opti_attr->set_enter_protected_mode (tcap[t_enter_protected_mode].string); - opti_attr->set_exit_protected_mode (tcap[t_exit_protected_mode].string); - opti_attr->set_enter_crossed_out_mode (tcap[t_enter_crossed_out_mode].string); - opti_attr->set_exit_crossed_out_mode (tcap[t_exit_crossed_out_mode].string); - opti_attr->set_enter_dbl_underline_mode (tcap[t_enter_dbl_underline_mode].string); - opti_attr->set_exit_dbl_underline_mode (tcap[t_exit_dbl_underline_mode].string); - opti_attr->set_set_attributes (tcap[t_set_attributes].string); - opti_attr->set_exit_attribute_mode (tcap[t_exit_attribute_mode].string); - opti_attr->set_enter_alt_charset_mode (tcap[t_enter_alt_charset_mode].string); - opti_attr->set_exit_alt_charset_mode (tcap[t_exit_alt_charset_mode].string); - opti_attr->set_enter_pc_charset_mode (tcap[t_enter_pc_charset_mode].string); - opti_attr->set_exit_pc_charset_mode (tcap[t_exit_pc_charset_mode].string); - opti_attr->set_a_foreground_color (tcap[t_set_a_foreground].string); - opti_attr->set_a_background_color (tcap[t_set_a_background].string); - opti_attr->set_foreground_color (tcap[t_set_foreground].string); - opti_attr->set_background_color (tcap[t_set_background].string); - opti_attr->set_term_color_pair (tcap[t_set_color_pair].string); - opti_attr->set_orig_pair (tcap[t_orig_pair].string); - opti_attr->set_orig_orig_colors (tcap[t_orig_colors].string); + opti_attr->set_enter_bold_mode (tcap[fc::t_enter_bold_mode].string); + opti_attr->set_exit_bold_mode (tcap[fc::t_exit_bold_mode].string); + opti_attr->set_enter_dim_mode (tcap[fc::t_enter_dim_mode].string); + opti_attr->set_exit_dim_mode (tcap[fc::t_exit_dim_mode].string); + opti_attr->set_enter_italics_mode (tcap[fc::t_enter_italics_mode].string); + opti_attr->set_exit_italics_mode (tcap[fc::t_exit_italics_mode].string); + opti_attr->set_enter_underline_mode (tcap[fc::t_enter_underline_mode].string); + opti_attr->set_exit_underline_mode (tcap[fc::t_exit_underline_mode].string); + opti_attr->set_enter_blink_mode (tcap[fc::t_enter_blink_mode].string); + opti_attr->set_exit_blink_mode (tcap[fc::t_exit_blink_mode].string); + opti_attr->set_enter_reverse_mode (tcap[fc::t_enter_reverse_mode].string); + opti_attr->set_exit_reverse_mode (tcap[fc::t_exit_reverse_mode].string); + opti_attr->set_enter_standout_mode (tcap[fc::t_enter_standout_mode].string); + opti_attr->set_exit_standout_mode (tcap[fc::t_exit_standout_mode].string); + opti_attr->set_enter_secure_mode (tcap[fc::t_enter_secure_mode].string); + opti_attr->set_exit_secure_mode (tcap[fc::t_exit_secure_mode].string); + opti_attr->set_enter_protected_mode (tcap[fc::t_enter_protected_mode].string); + opti_attr->set_exit_protected_mode (tcap[fc::t_exit_protected_mode].string); + opti_attr->set_enter_crossed_out_mode (tcap[fc::t_enter_crossed_out_mode].string); + opti_attr->set_exit_crossed_out_mode (tcap[fc::t_exit_crossed_out_mode].string); + opti_attr->set_enter_dbl_underline_mode (tcap[fc::t_enter_dbl_underline_mode].string); + opti_attr->set_exit_dbl_underline_mode (tcap[fc::t_exit_dbl_underline_mode].string); + opti_attr->set_set_attributes (tcap[fc::t_set_attributes].string); + opti_attr->set_exit_attribute_mode (tcap[fc::t_exit_attribute_mode].string); + opti_attr->set_enter_alt_charset_mode (tcap[fc::t_enter_alt_charset_mode].string); + opti_attr->set_exit_alt_charset_mode (tcap[fc::t_exit_alt_charset_mode].string); + opti_attr->set_enter_pc_charset_mode (tcap[fc::t_enter_pc_charset_mode].string); + opti_attr->set_exit_pc_charset_mode (tcap[fc::t_exit_pc_charset_mode].string); + opti_attr->set_a_foreground_color (tcap[fc::t_set_a_foreground].string); + opti_attr->set_a_background_color (tcap[fc::t_set_a_background].string); + opti_attr->set_foreground_color (tcap[fc::t_set_foreground].string); + opti_attr->set_background_color (tcap[fc::t_set_background].string); + opti_attr->set_term_color_pair (tcap[fc::t_set_color_pair].string); + opti_attr->set_orig_pair (tcap[fc::t_orig_pair].string); + opti_attr->set_orig_orig_colors (tcap[fc::t_orig_colors].string); opti_attr->setMaxColor (max_color); if ( ansi_default_color ) @@ -1593,7 +1593,7 @@ void FTerm::init_encoding() } else if ( isatty(stdout_no) && (std::strlen(termtype) > 0) - && (tcap[t_exit_alt_charset_mode].string != 0) ) + && (tcap[fc::t_exit_alt_charset_mode].string != 0) ) { vt100_console = true; Encoding = fc::VT100; @@ -1640,10 +1640,16 @@ void FTerm::init_encoding() void FTerm::init() { char* new_termtype = 0; + term_initialized = true; + init_term_object = this; x11_button_state = 0x03; - max_color = 1; + max_color = 1; + fd_tty = -1; + opti_move = new FOptiMove(); + opti_attr = new FOptiAttr(); + term = new FRect(0,0,0,0); + mouse = new FPoint(0,0); - output_buffer = new std::queue; vt100_alt_char = new std::map; encoding_set = new std::map; @@ -1664,7 +1670,6 @@ void FTerm::init() NewFont = \ VGAFont = \ ascii_console = \ - hidden_cursor = \ mouse_support = \ force_vt100 = \ tera_terminal = \ @@ -1677,59 +1682,14 @@ void FTerm::init() mintty_terminal = \ screen_terminal = \ tmux_terminal = \ - stop_terminal_updates = \ background_color_erase = false; - // term_attribute stores the current state of the terminal - term_attribute.code = '\0'; - term_attribute.fg_color = fc::Default; - term_attribute.bg_color = fc::Default; - term_attribute.bold = \ - term_attribute.dim = \ - term_attribute.italic = \ - term_attribute.underline = \ - term_attribute.blink = \ - term_attribute.reverse = \ - term_attribute.standout = \ - term_attribute.invisible = \ - term_attribute.protect = \ - term_attribute.crossed_out = \ - term_attribute.dbl_underline = \ - term_attribute.alt_charset = \ - term_attribute.pc_charset = \ - term_attribute.transparent = \ - term_attribute.trans_shadow = \ - term_attribute.inherit_bg = false; - - // next_attribute contains the state of the next printed character - next_attribute.code = '\0'; - next_attribute.fg_color = fc::Default; - next_attribute.bg_color = fc::Default; - next_attribute.bold = \ - next_attribute.dim = \ - next_attribute.italic = \ - next_attribute.underline = \ - next_attribute.blink = \ - next_attribute.reverse = \ - next_attribute.standout = \ - next_attribute.invisible = \ - next_attribute.protect = \ - next_attribute.crossed_out = \ - next_attribute.dbl_underline = \ - next_attribute.alt_charset = \ - next_attribute.pc_charset = \ - next_attribute.transparent = \ - next_attribute.trans_shadow = \ - next_attribute.inherit_bg = false; - // Preset to true cursor_optimisation = true; // assertion: programm start in cooked mode raw_mode = \ input_data_pending = \ - terminal_update_pending = \ - force_terminal_update = \ non_blocking_stdin = false; // init arrays with '\0' @@ -1747,15 +1707,6 @@ void FTerm::init() // initialize terminal and Linux console init_console(); - // create virtual terminal - createVTerm (*term); - - // create virtual desktop area - FPoint shadow_size(0,0); - createArea (*term, shadow_size, vdesktop); - vdesktop->visible = true; - active_area = vdesktop; - // make stdin non-blocking setNonBlockingInput(); @@ -1865,42 +1816,44 @@ void FTerm::init() init_encoding(); #ifdef F_HAVE_LIBGPM + // Enable the linux general purpose mouse (gpm) server gpm_mouse_enabled = enableGpmMouse(); + #endif // xterm mouse support - if ( tcap[t_key_mouse].string != 0 ) + if ( tcap[fc::t_key_mouse].string != 0 ) { mouse_support = true; enableXTermMouse(); } // enter 'keyboard_transmit' mode - if ( tcap[t_keypad_xmit].string ) + if ( tcap[fc::t_keypad_xmit].string ) { - putstring (tcap[t_keypad_xmit].string); + putstring (tcap[fc::t_keypad_xmit].string); std::fflush(stdout); } // save current cursor position - if ( tcap[t_save_cursor].string ) + if ( tcap[fc::t_save_cursor].string ) { - putstring (tcap[t_save_cursor].string); + putstring (tcap[fc::t_save_cursor].string); std::fflush(stdout); } // saves the screen and the cursor position - if ( tcap[t_enter_ca_mode].string ) + if ( tcap[fc::t_enter_ca_mode].string ) { - putstring (tcap[t_enter_ca_mode].string); + putstring (tcap[fc::t_enter_ca_mode].string); std::fflush(stdout); } // enable alternate charset - if ( tcap[t_enable_acs].string ) + if ( tcap[fc::t_enable_acs].string ) { - putstring (tcap[t_enable_acs].string); + putstring (tcap[fc::t_enable_acs].string); std::fflush(stdout); } @@ -1920,7 +1873,6 @@ void FTerm::init() } setRawMode(); - hideCursor(); if ( (xterm_terminal || urxvt_terminal) && ! rxvt_terminal ) { @@ -1943,11 +1895,11 @@ void FTerm::init() if ( linux_terminal && openConsole() == 0 ) { if ( isConsole() ) - if ( setLightBackgroundColors(true) != 0 ) + if ( setBlinkAsIntensity(true) != 0 ) max_color = 8; closeConsole(); - setConsoleCursor(fc::underscore_cursor); + setConsoleCursor(fc::underscore_cursor, true); } if ( linux_terminal && getFramebuffer_bpp() >= 4 ) @@ -2009,20 +1961,19 @@ void FTerm::finish() if ( xterm_title && xterm_terminal && ! rxvt_terminal ) setXTermTitle (*xterm_title); - showCursor(); setCookedMode(); // leave raw mode // turn off all attributes - if ( tcap[t_exit_attribute_mode].string ) + if ( tcap[fc::t_exit_attribute_mode].string ) { - putstring (tcap[t_exit_attribute_mode].string); + putstring (tcap[fc::t_exit_attribute_mode].string); std::fflush(stdout); } // turn off pc charset mode - if ( tcap[t_exit_pc_charset_mode].string ) + if ( tcap[fc::t_exit_pc_charset_mode].string ) { - putstring (tcap[t_exit_pc_charset_mode].string); + putstring (tcap[fc::t_exit_pc_charset_mode].string); std::fflush(stdout); } @@ -2051,15 +2002,15 @@ void FTerm::finish() if ( mintty_terminal ) { - // normal escape key mode + // switch to normal escape key mode putstring (CSI "?7727l"); std::fflush(stdout); } if ( linux_terminal ) { - setLightBackgroundColors (false); - setConsoleCursor(fc::default_cursor); + setBlinkAsIntensity (false); + setConsoleCursor(fc::default_cursor, false); } if ( kde_konsole ) @@ -2069,38 +2020,40 @@ void FTerm::finish() if ( linux_terminal && background_color_erase - && tcap[t_clear_screen].string ) + && tcap[fc::t_clear_screen].string ) { int rows = term->getHeight(); - putstring (tcap[t_clear_screen].string, rows); + putstring (tcap[fc::t_clear_screen].string, rows); } if ( mouse_support ) disableXTermMouse(); #ifdef F_HAVE_LIBGPM + if ( gpm_mouse_enabled ) disableGpmMouse(); // Disable gpm server + #endif // restores the screen and the cursor position - if ( tcap[t_exit_ca_mode].string ) + if ( tcap[fc::t_exit_ca_mode].string ) { - putstring (tcap[t_exit_ca_mode].string); + putstring (tcap[fc::t_exit_ca_mode].string); std::fflush(stdout); } // restore cursor to position of last save_cursor - if ( tcap[t_restore_cursor].string ) + if ( tcap[fc::t_restore_cursor].string ) { - putstring (tcap[t_restore_cursor].string); + putstring (tcap[fc::t_restore_cursor].string); std::fflush(stdout); } // leave 'keyboard_transmit' mode - if ( tcap[t_keypad_local].string ) + if ( tcap[fc::t_keypad_local].string ) { - putstring (tcap[t_keypad_local].string); + putstring (tcap[fc::t_keypad_local].string); std::fflush(stdout); } @@ -2124,9 +2077,6 @@ void FTerm::finish() if ( vt100_alt_char ) delete vt100_alt_char; - if ( output_buffer ) - delete output_buffer; - if ( sec_da ) delete sec_da; @@ -2139,8 +2089,17 @@ void FTerm::finish() if ( xterm_font ) delete xterm_font; - removeArea (vdesktop); - removeArea (vterm); + if ( mouse ) + delete mouse; + + if ( term ) + delete term; + + if ( opti_attr ) + delete opti_attr; + + if ( opti_move ) + delete opti_move; } //---------------------------------------------------------------------- @@ -2189,1083 +2148,6 @@ bool FTerm::charEncodable (uInt c) return bool(ch > 0 && ch != c); } -//---------------------------------------------------------------------- -void FTerm::createArea (const FRect& r, const FPoint& p, FTerm::term_area*& area) -{ - createArea ( r.getWidth() - , r.getHeight() - , p.getX() - , p.getY() - , area ); -} - -//---------------------------------------------------------------------- -void FTerm::createArea (int width, int height, int rsw, int bsh, term_area*& area) -{ - // initialize virtual window - area = new term_area; - - area->width = -1; - area->height = -1; - area->right_shadow = 0; - area->bottom_shadow = 0; - area->input_cursor_x = -1;; - area->input_cursor_y = -1;; - area->input_cursor_visible = false; - area->changes = 0; - area->text = 0; - area->visible = false; - area->widget = static_cast(this); - - resizeArea (width, height, rsw, bsh, area); -} - -//---------------------------------------------------------------------- -void FTerm::resizeArea (const FRect& r, const FPoint& p, FTerm::term_area* area) -{ - resizeArea ( r.getWidth() - , r.getHeight() - , p.getX() - , p.getY() - , area ); -} - -//---------------------------------------------------------------------- -void FTerm::resizeArea (int width, int height, int rsw, int bsh, term_area* area) -{ - int area_size; - FOptiAttr::char_data default_char; - line_changes unchanged; - - if ( ! area ) - return; - - area_size = (width+rsw) * (height+bsh); - - if ( area->height + area->bottom_shadow != height + bsh ) - { - if ( area->changes != 0 ) - delete[] area->changes; - - if ( area->text != 0 ) - delete[] area->text; - - area->changes = new line_changes[height + bsh]; - area->text = new FOptiAttr::char_data[area_size]; - } - else if ( area->width + area->right_shadow != width + rsw ) - { - if ( area->text != 0 ) - delete[] area->text; - - area->text = new FOptiAttr::char_data[area_size]; - } - else - return; - - area->width = width; - area->height = height; - area->right_shadow = rsw; - area->bottom_shadow = bsh; - - default_char.code = ' '; - default_char.fg_color = fc::Default; - default_char.bg_color = fc::Default; - default_char.bold = 0; - default_char.dim = 0; - default_char.italic = 0; - default_char.underline = 0; - default_char.blink = 0; - default_char.reverse = 0; - default_char.standout = 0; - default_char.invisible = 0; - default_char.protect = 0; - default_char.crossed_out = 0; - default_char.dbl_underline = 0; - default_char.alt_charset = 0; - default_char.pc_charset = 0; - default_char.transparent = 0; - default_char.trans_shadow = 0; - default_char.inherit_bg = 0; - - std::fill_n (area->text, area_size, default_char); - - unchanged.xmin = uInt(width+rsw); - unchanged.xmax = 0; - unchanged.trans_count = 0; - - std::fill_n (area->changes, height+bsh, unchanged); -} - -//---------------------------------------------------------------------- -void FTerm::removeArea (term_area*& area) -{ - // remove the virtual window - if ( area != 0 ) - { - if ( area->changes != 0 ) - { - delete[] area->changes; - area->changes = 0; - } - - if ( area->text != 0 ) - { - delete[] area->text; - area->text = 0; - } - - delete area; - area = 0; - } -} - -//---------------------------------------------------------------------- -void FTerm::restoreVTerm (const FRect& box) -{ - restoreVTerm ( box.getX() - , box.getY() - , box.getWidth() - , box.getHeight() ); -} - -//---------------------------------------------------------------------- -void FTerm::restoreVTerm (int x, int y, int w, int h) -{ - FOptiAttr::char_data* tc; // terminal character - FOptiAttr::char_data* sc; // shown character - FOptiAttr::char_data s_ch; // shadow character - FOptiAttr::char_data i_ch; // inherit background character - FWidget* widget; - - x--; - y--; - - if ( x < 0 ) - x = 0; - - if ( y < 0 ) - y = 0; - - if ( w < 0 || h < 0 ) - return; - - if ( x+w > vterm->width ) - w = vterm->width - x; - - if ( w < 0 ) - return; - - if ( y+h > vterm->height ) - h = vterm->height - y; - - if ( h < 0 ) - return; - - widget = static_cast(vterm->widget); - - for (register int ty=0; ty < h; ty++) - { - for (register int tx=0; tx < w; tx++) - { - tc = &vterm->text[(y+ty) * vterm->width + (x+tx)]; - sc = &vdesktop->text[(y+ty) * vdesktop->width + (x+tx)]; - - if ( widget->window_list && ! widget->window_list->empty() ) - { - FWidget::widgetList::const_iterator iter, end; - iter = widget->window_list->begin(); - end = widget->window_list->end(); - - while ( iter != end ) - { - term_area* win = (*iter)->getVWin(); - const FRect& geometry = (*iter)->getTermGeometryWithShadow(); - - // window visible and contains current character - if ( win && win->visible && geometry.contains(tx+x+1, ty+y+1) ) - { - FOptiAttr::char_data* tmp; - int win_x = (*iter)->getTermX() - 1; - int win_y = (*iter)->getTermY() - 1; - int line_len = win->width + win->right_shadow; - tmp = &win->text[(ty+y-win_y) * line_len + (tx+x-win_x)]; - - if ( ! tmp->transparent ) // current character not transparent - { - if ( tmp->trans_shadow ) // transparent shadow - { - // keep the current vterm character - std::memcpy (&s_ch, sc, sizeof(FOptiAttr::char_data)); - s_ch.fg_color = tmp->fg_color; - s_ch.bg_color = tmp->bg_color; - s_ch.reverse = false; - s_ch.standout = false; - - if ( s_ch.code == fc::LowerHalfBlock - || s_ch.code == fc::UpperHalfBlock - || s_ch.code == fc::LeftHalfBlock - || s_ch.code == fc::RightHalfBlock - || s_ch.code == fc::FullBlock ) - s_ch.code = ' '; - - sc = &s_ch; - } - else if ( tmp->inherit_bg ) - { - // add the covered background to this character - std::memcpy (&i_ch, tmp, sizeof(FOptiAttr::char_data)); - i_ch.bg_color = sc->bg_color; // last background color; - sc = &i_ch; - } - else // default - sc = tmp; - } - } - - ++iter; - } - } - - std::memcpy (tc, sc, sizeof(FOptiAttr::char_data)); - - if ( short(vterm->changes[y+ty].xmin) > x ) - vterm->changes[y+ty].xmin = uInt(x); - - if ( short(vterm->changes[y+ty].xmax) < x+w-1 ) - vterm->changes[y+ty].xmax = uInt(x+w-1); - } - } -} - -//---------------------------------------------------------------------- -FTerm::covered_state FTerm::isCovered ( const FPoint& pos - , FTerm::term_area* area) -{ - return isCovered (pos.getX(), pos.getY(), area); -} - -//---------------------------------------------------------------------- -FTerm::covered_state FTerm::isCovered (int x, int y, FTerm::term_area* area) -{ - bool found; - FTerm::covered_state is_covered; - FWidget* w; - - if ( ! area ) - return non_covered; - - is_covered = non_covered; - found = bool(area == vdesktop); - x++; - y++; - - w = static_cast(area->widget); - - if ( w->window_list && ! w->window_list->empty() ) - { - FWidget::widgetList::const_iterator iter, end; - iter = w->window_list->begin(); - end = w->window_list->end(); - - while ( iter != end ) - { - term_area* win = (*iter)->getVWin(); - const FRect& geometry = (*iter)->getTermGeometryWithShadow(); - - if ( win && found - && (*iter)->isVisible() - && (*iter)->isShown() - && geometry.contains(x,y) ) - { - FOptiAttr::char_data* tmp; - int win_x = (*iter)->getTermX() - 1; - int win_y = (*iter)->getTermY() - 1; - int line_len = win->width + win->right_shadow; - tmp = &win->text[(y-win_y-1) * line_len + (x-win_x-1)]; - - if ( tmp->trans_shadow ) - { - is_covered = half_covered; - } - else if ( ! tmp->transparent ) - { - is_covered = fully_covered; - break; - } - } - - if ( area == win ) - found = true; - - ++iter; - } - } - - return is_covered; -} - -//---------------------------------------------------------------------- -void FTerm::updateVTerm (bool on) -{ - vterm_updates = on; - - if ( on ) - updateVTerm (last_area); -} - -//---------------------------------------------------------------------- -void FTerm::updateVTerm (FTerm::term_area* area) -{ - int ax, ay, aw, ah, rsh, bsh, y_end, ol; - FOptiAttr::char_data* tc; // terminal character - FOptiAttr::char_data* ac; // area character - bool modified = false; - - if ( ! vterm_updates ) - { - last_area = area; - return; - } - - if ( ! area ) - return; - - if ( ! area->visible ) - return; - - ax = area->widget->getTermX() - 1; - ay = area->widget->getTermY() - 1; - aw = area->width; - ah = area->height; - rsh = area->right_shadow; - bsh = area->bottom_shadow; - ol = 0; // outside left - - if ( ax < 0 ) - { - ol = std::abs(ax); - ax = 0; - } - - if ( ah + bsh + ay > vterm->height ) - y_end = vterm->height - ay; - else - y_end = ah + bsh; - - for (register int y=0; y < y_end; y++) // line loop - { - int line_xmin = int(area->changes[y].xmin); - int line_xmax = int(area->changes[y].xmax); - - if ( line_xmin <= line_xmax ) - { - int _xmin, _xmax; - - if ( ax == 0 ) - line_xmin = ol; - - if ( aw + rsh + ax - ol >= vterm->width ) - line_xmax = vterm->width + ol - ax - 1; - - if ( ax + line_xmin >= vterm->width ) - continue; - - for (register int x=line_xmin; x <= line_xmax; x++) // column loop - { - int gx, gy, line_len; - FTerm::covered_state is_covered; - // global terminal positions - gx = ax + x; - gy = ay + y; - - if ( gx < 0 || gy < 0 ) - continue; - - line_len = aw + rsh; - ac = &area->text[y * line_len + x]; - tc = &vterm->text[gy * vterm->width + gx - ol]; - is_covered = isCovered(gx-ol, gy, area); // get covered state - - if ( is_covered != fully_covered ) - { - if ( is_covered == half_covered ) - { - // add the overlapping color to this character - FOptiAttr::char_data ch, oc; - std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); - oc = getOverlappedCharacter (gx+1 - ol, gy+1, area->widget); - ch.fg_color = oc.fg_color; - ch.bg_color = oc.bg_color; - ch.reverse = false; - ch.standout = false; - - if ( ch.code == fc::LowerHalfBlock - || ch.code == fc::UpperHalfBlock - || ch.code == fc::LeftHalfBlock - || ch.code == fc::RightHalfBlock - || ch.code == fc::FullBlock ) - ch.code = ' '; - - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else if ( ac->transparent ) // transparent - { - // restore one character on vterm - FOptiAttr::char_data ch; - ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else // not transparent - { - if ( ac->trans_shadow ) // transparent shadow - { - // get covered character + add the current color - FOptiAttr::char_data ch; - ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); - ch.fg_color = ac->fg_color; - ch.bg_color = ac->bg_color; - ch.reverse = false; - ch.standout = false; - - if ( ch.code == fc::LowerHalfBlock - || ch.code == fc::UpperHalfBlock - || ch.code == fc::LeftHalfBlock - || ch.code == fc::RightHalfBlock - || ch.code == fc::FullBlock ) - ch.code = ' '; - - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else if ( ac->inherit_bg ) - { - // add the covered background to this character - FOptiAttr::char_data ch, cc; - std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); - cc = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); - ch.bg_color = cc.bg_color; - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else // default - std::memcpy (tc, ac, sizeof(FOptiAttr::char_data)); - } - - modified = true; - } - else if ( ! modified ) - line_xmin++; // don't update covered character - } - - _xmin = ax + line_xmin - ol; - _xmax = ax + line_xmax; - - if ( _xmin < short(vterm->changes[ay+y].xmin) ) - vterm->changes[ay+y].xmin = uInt(_xmin); - - if ( _xmax >= vterm->width ) - _xmax = vterm->width - 1; - - if ( _xmax > short(vterm->changes[ay+y].xmax) ) - vterm->changes[ay+y].xmax = uInt(_xmax); - - area->changes[y].xmin = uInt(aw + rsh); - area->changes[y].xmax = 0; - } - } - - updateVTermCursor(area); -} - -//---------------------------------------------------------------------- -bool FTerm::updateVTermCursor (FTerm::term_area* area) -{ - if ( ! area ) - return false; - - if ( area != active_area ) - return false; - - if ( ! area->visible ) - return false; - - if ( area->input_cursor_visible ) - { - int cx, cy, ax, ay, x, y; - // cursor position - cx = area->input_cursor_x; - cy = area->input_cursor_y; - // widget position - ax = area->widget->getTermX() - 1; - ay = area->widget->getTermY() - 1; - // area position - x = ax + cx; - y = ay + cy; - - if ( isInsideArea(cx, cy, area) - && isInsideTerminal(x+1, y+1) - && isCovered(x, y, area) == non_covered ) - { - vterm->input_cursor_x = x; - vterm->input_cursor_y = y; - vterm->input_cursor_visible = true; - return true; - } - } - - vterm->input_cursor_visible = false; - return false; -} - -//---------------------------------------------------------------------- -bool FTerm::isInsideArea (int x, int y, FTerm::term_area* area) -{ - // Check whether the coordinates are within the area - int ax, ay, aw, ah; - ax = 0; - ay = 0; - aw = area->width; - ah = area->height; - FRect area_geometry(ax, ay, aw, ah); - - if ( area_geometry.contains(x,y) ) - return true; - else - return false; -} - -//---------------------------------------------------------------------- -void FTerm::setAreaCursor ( const FPoint& pos - , bool visible - , FTerm::term_area* area ) -{ - setAreaCursor (pos.getX(), pos.getY(), visible, area); -} - -//---------------------------------------------------------------------- -void FTerm::setAreaCursor (int x, int y, bool visible, FTerm::term_area* area) -{ - if ( ! area ) - return; - - area->input_cursor_x = x - 1; - area->input_cursor_y = y - 1; - area->input_cursor_visible = visible; - updateVTerm (area); -} - -//---------------------------------------------------------------------- -void FTerm::getArea (const FPoint& pos, FTerm::term_area* area) -{ - return getArea (pos.getX(), pos.getY(), area); -} - -//---------------------------------------------------------------------- -void FTerm::getArea (int ax, int ay, FTerm::term_area* area) -{ - // Copies a block from the virtual terminal position to the given area - int y_end; - int length; - FOptiAttr::char_data* tc; // terminal character - FOptiAttr::char_data* ac; // area character - - if ( ! area ) - return; - - ax--; - ay--; - - if ( area->height+ay > vterm->height ) - y_end = area->height - ay; - else - y_end = area->height; - - if ( area->width+ax > vterm->width ) - length = vterm->width - ax; - else - length = area->width; - - for (int y=0; y < y_end; y++) // line loop - { - tc = &vterm->text[(ay+y) * vterm->width + ax]; - ac = &area->text[y * area->width]; - std::memcpy (ac, tc, sizeof(FOptiAttr::char_data) * unsigned(length)); - - if ( short(area->changes[y].xmin) > 0 ) - area->changes[y].xmin = 0; - - if ( short(area->changes[y].xmax) < length-1 ) - area->changes[y].xmax = uInt(length-1); - } -} - -//---------------------------------------------------------------------- -void FTerm::getArea (const FRect& box, FTerm::term_area* area) -{ - getArea ( box.getX() - , box.getY() - , box.getWidth() - , box.getHeight() - , area ); -} - -//---------------------------------------------------------------------- -void FTerm::getArea (int x, int y, int w, int h, FTerm::term_area* area) -{ - // Copies a block from the virtual terminal rectangle to the given area - int y_end, length, dx, dy; - FOptiAttr::char_data* tc; // terminal character - FOptiAttr::char_data* ac; // area character - - if ( ! area ) - return; - - dx = x - area->widget->getTermX(); - dy = y - area->widget->getTermY(); - - if ( x < 0 || y < 0 ) - return; - - if ( y-1+h > vterm->height ) - y_end = vterm->height - y + 1; - else - y_end = h - 1; - - if ( x-1+w > vterm->width ) - length = vterm->width - x + 1; - else - length = w; - - if ( length < 1 ) - return; - - for (int _y=0; _y < y_end; _y++) // line loop - { - int line_len = area->width + area->right_shadow; - tc = &vterm->text[(y+_y-1) * vterm->width + x-1]; - ac = &area->text[(dy+_y) * line_len + dx]; - std::memcpy (ac, tc, sizeof(FOptiAttr::char_data) * unsigned(length)); - - if ( short(area->changes[dy+_y].xmin) > dx ) - area->changes[dy+_y].xmin = uInt(dx); - - if ( short(area->changes[dy+_y].xmax) < dx+length-1 ) - area->changes[dy+_y].xmax = uInt(dx+length-1); - } -} - -//---------------------------------------------------------------------- -void FTerm::putArea (const FPoint& pos, FTerm::term_area* area) -{ - // Copies the given area block to the virtual terminal position - if ( ! area ) - return; - - if ( ! area->visible ) - return; - - putArea (pos.getX(), pos.getY(), area); -} - -//---------------------------------------------------------------------- -void FTerm::putArea (int ax, int ay, FTerm::term_area* area) -{ - // Copies the given area block to the virtual terminal position - int aw, ah, rsh, bsh, y_end, length, ol; - FOptiAttr::char_data* tc; // terminal character - FOptiAttr::char_data* ac; // area character - - if ( ! area ) - return; - - if ( ! area->visible ) - return; - - ax--; - ay--; - aw = area->width; - ah = area->height; - rsh = area->right_shadow; - bsh = area->bottom_shadow; - ol = 0; // outside left - - if ( ax < 0 ) - { - ol = std::abs(ax); - ax = 0; - } - - if ( ay + ah + bsh > vterm->height ) - y_end = vterm->height - ay; - else - y_end = ah + bsh; - - if ( aw + rsh - ol + ax > vterm->width ) - length = vterm->width - ax; - else - length = aw + rsh - ol; - - if ( length < 1 ) - return; - - for (register int y=0; y < y_end; y++) // line loop - { - int line_len = aw + rsh; - - if ( area->changes[y].trans_count == 0 ) - { - // Line has only covered characters - tc = &vterm->text[(ay+y) * vterm->width + ax]; - ac = &area->text[y * line_len + ol]; - std::memcpy (tc, ac, sizeof(FOptiAttr::char_data) * unsigned(length)); - } - else - { - // Line has one or more transparent characters - for (register int x=0; x < length; x++) // column loop - { - tc = &vterm->text[(ay+y) * vterm->width + (ax+x)]; - ac = &area->text[y * line_len + ol + x]; - - if ( ac->transparent ) // transparent - { - // restore one character on vterm - FOptiAttr::char_data ch; - ch = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else // not transparent - { - if ( ac->trans_shadow ) // transparent shadow - { - // get covered character + add the current color - FOptiAttr::char_data ch; - ch = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); - ch.fg_color = ac->fg_color; - ch.bg_color = ac->bg_color; - ch.reverse = false; - ch.standout = false; - - if ( ch.code == fc::LowerHalfBlock - || ch.code == fc::UpperHalfBlock - || ch.code == fc::LeftHalfBlock - || ch.code == fc::RightHalfBlock - || ch.code == fc::FullBlock ) - ch.code = ' '; - - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else if ( ac->inherit_bg ) - { - // add the covered background to this character - FOptiAttr::char_data ch, cc; - std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); - cc = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); - ch.bg_color = cc.bg_color; - std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); - } - else // default - std::memcpy (tc, ac, sizeof(FOptiAttr::char_data)); - } - } - } - - if ( ax < short(vterm->changes[ay+y].xmin) ) - vterm->changes[ay+y].xmin = uInt(ax); - - if ( ax+length-1 > short(vterm->changes[ay+y].xmax) ) - vterm->changes[ay+y].xmax = uInt(ax+length-1); - } -} - -//---------------------------------------------------------------------- -void FTerm::scrollAreaForward (FTerm::term_area* area) -{ - 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; - - // clear with the current attributes and space characters - std::memcpy (&nc, &next_attribute, sizeof(FOptiAttr::char_data)); - nc.code = ' '; - - if ( ! area ) - return; - - total_width = area->width + area->right_shadow; - w = uInt(total_width); - - if ( area->right_shadow == 0 ) - { - int area_size = area->width * area->height; - std::fill_n (area->text, area_size, nc); - } - else - { - 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, nc); - std::fill_n (&area->text[pos+area->width], area->right_shadow, t_char); - } - - for (int y=0; y < area->bottom_shadow; y++) - { - int pos = total_width * (y + area->height); - std::fill_n (&area->text[pos], total_width, t_char); - } - } - - for (int i=0; i < area->height; i++) - { - - area->changes[i].xmin = 0; - area->changes[i].xmax = w - 1; - - 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); - else - area->changes[i].trans_count = 0; - } - - for (int i=0; i < area->bottom_shadow; i++) - { - int y = area->height + i; - area->changes[y].xmin = 0; - area->changes[y].xmax = w - 1; - area->changes[y].trans_count = w; - } - - updateVTerm (area); -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getCharacter ( int type - , const FPoint& pos - , FTerm* obj ) -{ - return getCharacter (type, pos.getX(), pos.getY(), obj); -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getCharacter ( int char_type - , int x - , int y - , FTerm* obj ) -{ - // get the overlapped or the covered character for a position - int xx,yy; - FOptiAttr::char_data* cc; // covered character - FOptiAttr::char_data s_ch; // shadow character - FOptiAttr::char_data i_ch; // inherit background character - FWidget* w; - - x--; - y--; - xx = x; - yy = y; - - if ( xx < 0 ) - xx = 0; - - if ( yy < 0 ) - yy = 0; - - if ( xx >= vterm->width ) - xx = vterm->width - 1; - - if ( yy >= vterm->height ) - yy = vterm->height - 1; - - cc = &vdesktop->text[yy * vdesktop->width + xx]; - w = static_cast(obj); - - if ( w->window_list && ! w->window_list->empty() ) - { - FWidget::widgetList::const_iterator iter, end; - // get the window layer of this object - int layer = FWindow::getWindowLayer(w); - iter = w->window_list->begin(); - end = w->window_list->end(); - - while ( iter != end ) - { - bool significant_char; - - // char_type can be "overlapped_character" - // or "covered_character" - if ( char_type == covered_character ) - significant_char = bool(layer >= FWindow::getWindowLayer(*iter)); - else - significant_char = bool(layer < FWindow::getWindowLayer(*iter)); - - if ( obj && *iter != obj && significant_char ) - { - term_area* win = (*iter)->getVWin(); - const FRect& geometry = (*iter)->getTermGeometryWithShadow(); - - // window visible and contains current character - if ( win && win->visible && geometry.contains(x+1,y+1) ) - { - FOptiAttr::char_data* tmp; - int win_x = (*iter)->getTermX() - 1; - int win_y = (*iter)->getTermY() - 1; - int line_len = win->width + win->right_shadow; - tmp = &win->text[(y-win_y) * line_len + (x-win_x)]; - - // current character not transparent - if ( ! tmp->transparent ) - { - if ( tmp->trans_shadow ) // transparent shadow - { - // keep the current vterm character - std::memcpy (&s_ch, cc, sizeof(FOptiAttr::char_data)); - s_ch.fg_color = tmp->fg_color; - s_ch.bg_color = tmp->bg_color; - s_ch.reverse = false; - s_ch.standout = false; - cc = &s_ch; - } - else if ( tmp->inherit_bg ) - { - // add the covered background to this character - std::memcpy (&i_ch, tmp, sizeof(FOptiAttr::char_data)); - i_ch.bg_color = cc->bg_color; // last background color - cc = &i_ch; - } - else // default - cc = tmp; - } - } - } - else if ( char_type == covered_character ) - break; - - ++iter; - } - } - - return *cc; -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getCoveredCharacter ( int x - , int y - , FTerm* obj) -{ - return getCharacter (covered_character, x, y, obj); -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getCoveredCharacter ( const FPoint& pos - , FTerm* obj ) -{ - return getCharacter (covered_character, pos.getX(), pos.getY(), obj); -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getOverlappedCharacter ( int x - , int y - , FTerm* obj) -{ - return getCharacter (overlapped_character, x, y, obj); -} - -//---------------------------------------------------------------------- -FOptiAttr::char_data FTerm::getOverlappedCharacter ( const FPoint& pos - , FTerm* obj ) -{ - return getCharacter (overlapped_character, pos.getX(), pos.getY(), obj); -} - // public methods of FTerm //---------------------------------------------------------------------- @@ -3474,19 +2356,54 @@ bool FTerm::setOldFont() } //---------------------------------------------------------------------- -void FTerm::setConsoleCursor (fc::consoleCursorStyle style) +void FTerm::setConsoleCursor (fc::consoleCursorStyle style, bool hidden) { // Set cursor style in linux console - if ( linux_terminal ) - { - console_cursor_style = style; + if ( ! linux_terminal ) + return; - if ( hidden_cursor ) - return; + console_cursor_style = style; - putstringf (CSI "?%dc", style); - std::fflush(stdout); - } + if ( hidden ) + return; + + putstringf (CSI "?%dc", style); + std::fflush(stdout); +} + +//---------------------------------------------------------------------- +char* FTerm::moveCursor (int xold, int yold, int xnew, int ynew) +{ + // returns the cursor move string + if ( cursor_optimisation ) + return opti_move->moveCursor (xold, yold, xnew, ynew); + else + return tgoto(tcap[fc::t_cursor_address].string, xnew, ynew); +} + +//---------------------------------------------------------------------- +char* FTerm::enableCursor() +{ + char*& vs = tcap[fc::t_cursor_visible].string; + char*& ve = tcap[fc::t_cursor_normal].string; + + if ( ve ) + return ve; + else if ( vs ) + return vs; + + return 0; +} + +//---------------------------------------------------------------------- +char* FTerm::disableCursor() +{ + char*& vi = tcap[fc::t_cursor_invisible].string; + + if ( vi ) + return vi; + + return 0; } //---------------------------------------------------------------------- @@ -3528,168 +2445,6 @@ void FTerm::setTermSize (int term_width, int term_height) } } -//---------------------------------------------------------------------- -void FTerm::createVTerm (const FRect& r) -{ - // initialize virtual terminal - const FPoint shadow(0,0); - createArea (r, shadow, vterm); -} - -//---------------------------------------------------------------------- -void FTerm::createVTerm (int width, int height) -{ - // initialize virtual terminal - createArea (width, height, 0, 0, vterm); -} - -//---------------------------------------------------------------------- -void FTerm::resizeVTerm (const FRect& r) -{ - const FPoint shadow(0,0); - resizeArea (r, shadow, vterm); -} - -//---------------------------------------------------------------------- -void FTerm::resizeVTerm (int width, int height) -{ - resizeArea (width, height, 0, 0, vterm); -} - -//---------------------------------------------------------------------- -void FTerm::putVTerm() -{ - for (int i=0; i < vterm->height; i++) - { - vterm->changes[i].xmin = 0; - vterm->changes[i].xmax = uInt(vterm->width - 1); - } - - updateTerminal(); -} - -//---------------------------------------------------------------------- -void FTerm::updateTerminal (bool on) -{ - stop_terminal_updates = bool(! on); - - if ( on ) - updateTerminal(); -} - -//---------------------------------------------------------------------- -void FTerm::updateTerminal() -{ - term_area* vt; - int term_width, term_height; - - if ( stop_terminal_updates - || static_cast(term_object)->isQuit() ) - return; - - if ( ! force_terminal_update ) - { - if ( ! terminal_updates ) - return; - - if ( input_data_pending ) - { - terminal_update_pending = true; - return; - } - } - - vt = vterm; - term_width = vt->width - 1; - term_height = vt->height - 1; - - for (register uInt y=0; y < uInt(vt->height); y++) - { - uInt change_xmax = vt->changes[y].xmax; - - if ( vt->changes[y].xmin <= vt->changes[y].xmax ) - { - uInt change_xmin = vt->changes[y].xmin; - setTermXY (int(change_xmin), int(y)); - - for ( register uInt x=change_xmin; - x <= change_xmax; - x++ ) - { - FOptiAttr::char_data* print_char; - print_char = &vt->text[y * uInt(vt->width) + x]; - - if ( term_pos->getX() == term_width - && term_pos->getY() == term_height ) - appendLowerRight (print_char); - else - appendCharacter (print_char); - - term_pos->x_ref()++; - } - - vt->changes[y].xmin = uInt(vt->width); - vt->changes[y].xmax = 0; - } - - // cursor wrap - if ( term_pos->getX() > term_width ) - { - if ( term_pos->getY() == term_height ) - term_pos->x_ref()--; - else - { - if ( eat_nl_glitch ) - { - term_pos->setPoint(-1,-1); - } - else if ( automatic_right_margin ) - { - term_pos->setX(0); - term_pos->y_ref()++; - } - else - term_pos->x_ref()--; - } - } - } - - // sets the new input cursor position - updateTerminalCursor(); -} - -//---------------------------------------------------------------------- -bool FTerm::updateTerminalCursor() -{ - // updates the input cursor visibility and the position - if ( vterm && vterm->input_cursor_visible ) - { - int x = vterm->input_cursor_x; - int y = vterm->input_cursor_y; - - if ( isInsideTerminal(x+1, y+1) ) - { - setTermXY (x,y); - showCursor(); - return true; - } - } - else - hideCursor(); - - return false; -} - -//---------------------------------------------------------------------- -bool FTerm::isInsideTerminal (int x, int y) -{ - // Check whether the coordinates are within the virtual terminal - if ( term->contains(x,y) ) - return true; - else - return false; -} - //---------------------------------------------------------------------- void FTerm::setKDECursor (fc::kdeKonsoleCursorShape style) { @@ -3975,8 +2730,8 @@ void FTerm::saveColorMap() //---------------------------------------------------------------------- void FTerm::resetColorMap() { - char* op = tcap[t_orig_pair].string; - char* oc = tcap[t_orig_colors].string; + char*& op = tcap[fc::t_orig_pair].string; + char*& oc = tcap[fc::t_orig_colors].string; if ( op ) putstring (op); @@ -4010,8 +2765,8 @@ void FTerm::resetColorMap() //---------------------------------------------------------------------- void FTerm::setPalette (short index, int r, int g, int b) { - char* Ic = tcap[t_initialize_color].string; - char* Ip = tcap[t_initialize_pair].string; + char*& Ic = tcap[fc::t_initialize_color].string; + char*& Ip = tcap[fc::t_initialize_pair].string; index = FOptiAttr::vga2ansi(index); @@ -4119,46 +2874,6 @@ bool FTerm::gpmMouse (bool on) } #endif // F_HAVE_LIBGPM -//---------------------------------------------------------------------- -void FTerm::setTermXY (register int x, register int y) -{ - // sets the hardware cursor to the given (x,y) position - int term_x, term_y, term_width, term_height; - char* move_str; - - if ( term_pos->getX() == x && term_pos->getY() == y ) - return; - - term_width = term->getWidth(); - term_height = term->getHeight(); - - if ( x >= term_width ) - { - y += x / term_width; - x %= term_width; - } - - if ( term_pos->getY() >= term_height ) - term_pos->setY(term_height - 1); - - if ( y >= term_height ) - y = term_height - 1; - - term_x = term_pos->getX(); - term_y = term_pos->getY(); - - if ( cursor_optimisation ) - move_str = opti_move->cursor_move (term_x, term_y, x, y); - else - move_str = tgoto(tcap[t_cursor_address].string, x, y); - - if ( move_str ) - appendOutputBuffer(move_str); - - flush_out(); - term_pos->setPoint(x,y); -} - //---------------------------------------------------------------------- void FTerm::setBeep (int Hz, int ms) { @@ -4195,50 +2910,13 @@ void FTerm::resetBeep() //---------------------------------------------------------------------- void FTerm::beep() { - if ( tcap[t_bell].string ) + if ( tcap[fc::t_bell].string ) { - putstring (tcap[t_bell].string); + putstring (tcap[fc::t_bell].string); std::fflush(stdout); } } -//---------------------------------------------------------------------- -bool FTerm::hideCursor (bool on) -{ - char *vi, *vs, *ve; - - if ( on == hidden_cursor ) - return hidden_cursor; - - vi = tcap[t_cursor_invisible].string; - vs = tcap[t_cursor_visible].string; - ve = tcap[t_cursor_normal].string; - - if ( on ) - { - if ( vi ) - appendOutputBuffer (vi); - - hidden_cursor = true; // global - } - else - { - if ( ve ) - appendOutputBuffer (ve); - else if ( vs ) - appendOutputBuffer (vs); - - hidden_cursor = false; - } - - flush_out(); - - if ( ! hidden_cursor && linux_terminal ) - setConsoleCursor (console_cursor_style); - - return hidden_cursor; -} - //---------------------------------------------------------------------- void FTerm::setEncoding (std::string enc) { @@ -4315,9 +2993,9 @@ bool FTerm::setNonBlockingInput (bool on) //---------------------------------------------------------------------- bool FTerm::scrollTermForward() { - if ( tcap[t_scroll_forward].string ) + if ( tcap[fc::t_scroll_forward].string ) { - putstring (tcap[t_scroll_forward].string); + putstring (tcap[fc::t_scroll_forward].string); std::fflush(stdout); return true; } @@ -4328,9 +3006,9 @@ bool FTerm::scrollTermForward() //---------------------------------------------------------------------- bool FTerm::scrollTermReverse() { - if ( tcap[t_scroll_reverse].string ) + if ( tcap[fc::t_scroll_reverse].string ) { - putstring (tcap[t_scroll_reverse].string); + putstring (tcap[fc::t_scroll_reverse].string); std::fflush(stdout); return true; } @@ -4491,594 +3169,6 @@ FString FTerm::getSecDA() return sec_da_str; } -//---------------------------------------------------------------------- -int FTerm::printf (const wchar_t* format, ...) -{ - assert ( format != 0 ); - const int buf_size = 1024; - wchar_t buffer[buf_size]; - va_list args; - - va_start (args, format); - std::vswprintf (buffer, buf_size, format, args); - va_end (args); - - FString str(buffer); - return print(str); -} - -//---------------------------------------------------------------------- -int FTerm::printf (const char* format, ...) -{ - assert ( format != 0 ); - int len; - char buf[512]; - char* buffer; - va_list args; - - buffer = buf; - va_start (args, format); - len = std::vsnprintf (buffer, sizeof(buf), format, args); - va_end (args); - - if ( len >= int(sizeof(buf)) ) - { - buffer = new char[len+1](); - va_start (args, format); - std::vsnprintf (buffer, uLong(len+1), format, args); - va_end (args); - } - - FString str(buffer); - int ret = print(str); - - if ( buffer != buf ) - delete[] buffer; - - return ret; -} - -//---------------------------------------------------------------------- -int FTerm::print (const std::wstring& s) -{ - assert ( ! s.empty() ); - return print (FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, const std::wstring& s) -{ - assert ( area != 0 ); - assert ( ! s.empty() ); - return print (area, FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (const wchar_t* s) -{ - assert ( s != 0 ); - return print (FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, const wchar_t* s) -{ - assert ( area != 0 ); - assert ( s != 0 ); - return print (area, FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (const char* s) -{ - assert ( s != 0 ); - FString str(s); - return print(str); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, const char* s) -{ - assert ( area != 0 ); - assert ( s != 0 ); - FString str(s); - return print(area, str); -} - -//---------------------------------------------------------------------- -int FTerm::print (const std::string& s) -{ - assert ( ! s.empty() ); - return print (FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, const std::string& s) -{ - assert ( area != 0 ); - assert ( ! s.empty() ); - return print (area, FString(s)); -} - -//---------------------------------------------------------------------- -int FTerm::print (FString& s) -{ - assert ( ! s.isNull() ); - term_area* area; - FWidget* w; - w = static_cast(this); - area = w->getPrintArea(); - - if ( ! area ) - { - FWidget* root = w->getRootWidget(); - area = vdesktop; - - if ( ! root ) - return -1; - } - - return print (area, s); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, FString& s) -{ - assert ( ! s.isNull() ); - register int len = 0; - const wchar_t* p; - FWidget* window; - - if ( ! area ) - return -1; - - window = area->widget; - - if ( ! window ) - return -1; - - p = s.wc_str(); - - if ( p ) - { - while ( *p ) - { - int rsh, bsh; - - switch ( *p ) - { - case '\n': - cursor->y_ref()++; - - case '\r': - cursor->x_ref() = 1; - break; - - case '\t': - cursor->x_ref() = short ( uInt(cursor->x_ref()) - + tabstop - - uInt(cursor->x_ref()) - + 1 - % tabstop ); - break; - - case '\b': - cursor->x_ref()--; - break; - - case '\a': - beep(); - break; - - default: - { - short x = short(cursor->getX()); - short y = short(cursor->getY()); - - FOptiAttr::char_data nc; // next character - nc.code = *p; - nc.fg_color = next_attribute.fg_color; - nc.bg_color = next_attribute.bg_color; - nc.bold = next_attribute.bold; - nc.dim = next_attribute.dim; - nc.italic = next_attribute.italic; - nc.underline = next_attribute.underline; - nc.blink = next_attribute.blink; - nc.reverse = next_attribute.reverse; - nc.standout = next_attribute.standout; - nc.invisible = next_attribute.invisible; - nc.protect = next_attribute.protect; - nc.crossed_out = next_attribute.crossed_out; - nc.dbl_underline = next_attribute.dbl_underline; - nc.alt_charset = next_attribute.alt_charset; - nc.pc_charset = next_attribute.pc_charset; - nc.transparent = next_attribute.transparent; - nc.trans_shadow = next_attribute.trans_shadow; - nc.inherit_bg = next_attribute.inherit_bg; - - int ax = x - window->getTermX(); - int ay = y - window->getTermY(); - - if ( area - && ax >= 0 && ay >= 0 - && ax < area->width + area->right_shadow - && ay < area->height + area->bottom_shadow ) - { - FOptiAttr::char_data* ac; // area character - int line_len = area->width + area->right_shadow; - ac = &area->text[ay * line_len + ax]; - - if ( *ac != nc ) // compare with an overloaded operator - { - if ( ( ! ac->transparent && nc.transparent ) - || ( ! ac->trans_shadow && nc.trans_shadow ) - || ( ! ac->inherit_bg && nc.inherit_bg ) ) - { - // add one transparent character form line - area->changes[ay].trans_count++; - } - else if ( ( ac->transparent && ! nc.transparent ) - || ( ac->trans_shadow && ! nc.trans_shadow ) - || ( ac->inherit_bg && ! nc.inherit_bg ) ) - { - // remove one transparent character from line - area->changes[ay].trans_count--; - } - - // copy character to area - std::memcpy (ac, &nc, sizeof(nc)); - - if ( ax < short(area->changes[ay].xmin) ) - area->changes[ay].xmin = uInt(ax); - - if ( ax > short(area->changes[ay].xmax) ) - area->changes[ay].xmax = uInt(ax); - } - } - - cursor->x_ref()++; - } - } - - rsh = area->right_shadow; - bsh = area->bottom_shadow; - const FRect& area_geometry = window->getTermGeometry(); - - if ( cursor->x_ref() > area_geometry.getX2()+rsh ) - { - cursor->x_ref() = short(window->getTermX()); - cursor->y_ref()++; - } - - if ( cursor->y_ref() > area_geometry.getY2()+bsh ) - { - cursor->y_ref()--; - break; - } - - p++; - len++; - } // end of while - - updateVTerm (area); - } - - return len; -} - -//---------------------------------------------------------------------- -int FTerm::print (register int c) -{ - term_area* area; - FWidget* w; - w = static_cast(this); - area = w->getPrintArea(); - - if ( ! area ) - { - FWidget* root = w->getRootWidget(); - area = vdesktop; - - if ( ! root ) - return -1; - } - - return print (area, c); -} - -//---------------------------------------------------------------------- -int FTerm::print (FTerm::term_area* area, register int c) -{ - FOptiAttr::char_data nc; // next character - FWidget* window; - int rsh, bsh, ax, ay; - short x, y; - - if ( ! area ) - return -1; - - nc.code = c; - nc.fg_color = next_attribute.fg_color; - nc.bg_color = next_attribute.bg_color; - nc.bold = next_attribute.bold; - nc.dim = next_attribute.dim; - nc.italic = next_attribute.italic; - nc.underline = next_attribute.underline; - nc.blink = next_attribute.blink; - nc.reverse = next_attribute.reverse; - nc.standout = next_attribute.standout; - nc.invisible = next_attribute.invisible; - nc.protect = next_attribute.protect; - nc.crossed_out = next_attribute.crossed_out; - nc.dbl_underline = next_attribute.dbl_underline; - nc.alt_charset = next_attribute.alt_charset; - nc.pc_charset = next_attribute.pc_charset; - nc.transparent = next_attribute.transparent; - nc.trans_shadow = next_attribute.trans_shadow; - nc.inherit_bg = next_attribute.inherit_bg; - - x = short(cursor->getX()); - y = short(cursor->getY()); - window = area->widget; - - if ( ! window ) - return -1; - - ax = x - window->getTermX(); - ay = y - window->getTermY(); - - if ( ax >= 0 && ay >= 0 - && ax < area->width + area->right_shadow - && ay < area->height + area->bottom_shadow ) - { - FOptiAttr::char_data* ac; // area character - int line_len = area->width + area->right_shadow; - ac = &area->text[ay * line_len + ax]; - - if ( *ac != nc ) // compare with an overloaded operator - { - if ( ( ! ac->transparent && nc.transparent ) - || ( ! ac->trans_shadow && nc.trans_shadow ) - || ( ! ac->inherit_bg && nc.inherit_bg ) ) - { - // add one transparent character form line - area->changes[ay].trans_count++; - } - - if ( ( ac->transparent && ! nc.transparent ) - || ( ac->trans_shadow && ! nc.trans_shadow ) - || ( ac->inherit_bg && ! nc.inherit_bg ) ) - { - // remove one transparent character from line - area->changes[ay].trans_count--; - } - - // copy character to area - std::memcpy (ac, &nc, sizeof(nc)); - - if ( ax < short(area->changes[ay].xmin) ) - area->changes[ay].xmin = uInt(ax); - - if ( ax > short(area->changes[ay].xmax) ) - area->changes[ay].xmax = uInt(ax); - } - } - - cursor->x_ref()++; - rsh = area->right_shadow; - bsh = area->bottom_shadow; - const FRect& area_geometry = window->getTermGeometry(); - - if ( cursor->x_ref() > area_geometry.getX2()+rsh ) - { - cursor->x_ref() = short(window->getTermX()); - cursor->y_ref()++; - } - - if ( cursor->y_ref() > area_geometry.getY2()+bsh ) - { - cursor->y_ref()--; - updateVTerm (area); - return -1; - } - - updateVTerm (area); - return 1; -} - -//---------------------------------------------------------------------- -inline void FTerm::newFontChanges (FOptiAttr::char_data*& next_char) -{ - // NewFont special cases - if ( NewFont ) - { - switch ( next_char->code ) - { - case fc::LowerHalfBlock: - next_char->code = fc::UpperHalfBlock; - // fall through - case fc::NF_rev_left_arrow2: - case fc::NF_rev_right_arrow2: - case fc::NF_rev_border_corner_upper_right: - case fc::NF_rev_border_line_right: - case fc::NF_rev_border_line_vertical_left: - case fc::NF_rev_border_corner_lower_right: - case fc::NF_rev_up_arrow2: - case fc::NF_rev_down_arrow2: - case fc::NF_rev_up_arrow1: - case fc::NF_rev_down_arrow1: - case fc::NF_rev_left_arrow1: - case fc::NF_rev_right_arrow1: - case fc::NF_rev_menu_button1: - case fc::NF_rev_menu_button2: - case fc::NF_rev_up_pointing_triangle1: - case fc::NF_rev_down_pointing_triangle1: - case fc::NF_rev_up_pointing_triangle2: - case fc::NF_rev_down_pointing_triangle2: - case fc::NF_rev_menu_button3: - case fc::NF_rev_border_line_right_and_left: - // swap foreground and background color - std::swap (next_char->fg_color, next_char->bg_color); - break; - - default: - break; - } - } -} - -//---------------------------------------------------------------------- -inline void FTerm::charsetChanges (FOptiAttr::char_data*& next_char) -{ - if ( Encoding == fc::UTF8 ) - return; - - uInt code = uInt(next_char->code); - uInt ch = charEncode(code); - - if ( ch != code ) - { - if ( ch == 0 ) - { - next_char->code = int(charEncode(code, fc::ASCII)); - return; - } - - next_char->code = int(ch); - - if ( Encoding == fc::VT100 ) - next_char->alt_charset = true; - else if ( Encoding == fc::PC ) - { - next_char->pc_charset = true; - - if ( xterm_terminal && utf8_console && ch < 0x20 ) // Character 0x00..0x1f - next_char->code = int(charEncode(code, fc::ASCII)); - } - } -} - -//---------------------------------------------------------------------- -inline void FTerm::appendCharacter (FOptiAttr::char_data*& next_char) -{ - newFontChanges (next_char); - charsetChanges (next_char); - - appendAttributes (next_char); - appendOutputBuffer (next_char->code); -} - -//---------------------------------------------------------------------- -inline void FTerm::appendAttributes (FOptiAttr::char_data*& next_attr) -{ - char* attr_str; - FOptiAttr::char_data* term_attr = &term_attribute; - - // generate attribute string for the next character - attr_str = opti_attr->change_attribute (term_attr, next_attr); - - if ( attr_str ) - appendOutputBuffer (attr_str); -} - -//---------------------------------------------------------------------- -int FTerm::appendLowerRight (FOptiAttr::char_data*& screen_char) -{ - char* SA = tcap[t_enter_am_mode].string; - char* RA = tcap[t_exit_am_mode].string; - - if ( ! automatic_right_margin ) - { - appendCharacter (screen_char); - } - else if ( SA && RA ) - { - appendOutputBuffer (RA); - appendCharacter (screen_char); - appendOutputBuffer (SA); - } - else - { - int x, y; - char* IC = tcap[t_parm_ich].string; - char* im = tcap[t_enter_insert_mode].string; - char* ei = tcap[t_exit_insert_mode].string; - char* ip = tcap[t_insert_padding].string; - char* ic = tcap[t_insert_character].string; - - x = term->getWidth() - 2; - y = term->getHeight() - 1; - setTermXY (x, y); - appendCharacter (screen_char); - term_pos->x_ref()++; - - setTermXY (x, y); - screen_char--; - - if ( IC ) - { - appendOutputBuffer (tparm(IC, 1)); - appendCharacter (screen_char); - } - else if ( im && ei ) - { - appendOutputBuffer (im); - appendCharacter (screen_char); - - if ( ip ) - appendOutputBuffer (ip); - - appendOutputBuffer (ei); - } - else if ( ic ) - { - appendOutputBuffer (ic); - appendCharacter (screen_char); - - if ( ip ) - appendOutputBuffer (ip); - } - } - - return screen_char->code; -} - -//---------------------------------------------------------------------- -inline void FTerm::appendOutputBuffer (std::string& s) -{ - const char* c_string = s.c_str(); - tputs (c_string, 1, appendOutputBuffer); -} - -//---------------------------------------------------------------------- -inline void FTerm::appendOutputBuffer (const char* s) -{ - tputs (s, 1, appendOutputBuffer); -} - -//---------------------------------------------------------------------- -int FTerm::appendOutputBuffer (int ch) -{ - output_buffer->push(ch); - - if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE ) - flush_out(); - - return ch; -} - -//---------------------------------------------------------------------- -void FTerm::flush_out() -{ - while ( ! output_buffer->empty() ) - { - Fputchar (output_buffer->front()); - output_buffer->pop(); - } - - std::fflush(stdout); -} - //---------------------------------------------------------------------- void FTerm::putstringf (const char* format, ...) { @@ -5094,7 +3184,6 @@ void FTerm::putstringf (const char* format, ...) tputs (buffer, 1, std::putchar); } - //---------------------------------------------------------------------- inline void FTerm::putstring (const char* s, int affcnt) { diff --git a/src/fterm.h b/src/fterm.h index ecc47076..973473c8 100644 --- a/src/fterm.h +++ b/src/fterm.h @@ -21,13 +21,8 @@ // : ▕▁▁▁▁▁▁▁▁▏ // : // : *▕▔▔▔▔▔▔▔▏ -// :- - - -▕ FRect ▏ -// : ▕▁▁▁▁▁▁▁▏ -// : -// : *▕▔▔▔▔▔▔▔▔▔▏ -// └- - - -▕ FWidget ▏ -// ▕▁▁▁▁▁▁▁▁▁▏ -// +// └- - - -▕ FRect ▏ +// ▕▁▁▁▁▁▁▁▏ #ifndef _FTERM_H #define _FTERM_H @@ -38,16 +33,17 @@ #include #endif -#include // Linux framebuffer console +#include // Linux framebuffer console +#include // need for gpm keyboard modifiers -#include +#include // is deprecated, use instead #include #include -#include // is deprecated, use instead +#include #include #include -#include // termcap +#include // termcap #include #include @@ -63,6 +59,7 @@ #include "fpoint.h" #include "frect.h" #include "fstring.h" +#include "ftermcap.h" #ifdef F_HAVE_LIBGPM @@ -88,11 +85,6 @@ // parseKeyString return value #define NEED_MORE_DATA -1 -// Buffer size for character output on the terminal -#define TERMINAL_OUTPUT_BUFFER_SIZE 32768 - -// class forward declaration -class FWidget; //---------------------------------------------------------------------- // class FTerm @@ -104,16 +96,13 @@ class FWidget; class FTerm { private: - static std::queue* output_buffer; static std::map * vt100_alt_char; static std::map * encoding_set; + static FTermcap::tcap_map* tcap; - static bool hidden_cursor; static bool mouse_support; static bool raw_mode; static bool input_data_pending; - static bool terminal_update_pending; - static bool force_terminal_update; static bool non_blocking_stdin; static bool gpm_mouse_enabled; static bool pc_charset_console; @@ -140,9 +129,6 @@ class FTerm static bool linux_terminal; static bool screen_terminal; static bool tmux_terminal; - static bool terminal_updates; - static bool stop_terminal_updates; - static bool vterm_updates; static bool background_color_erase; static bool automatic_left_margin; static bool automatic_right_margin; @@ -155,9 +141,8 @@ class FTerm static char* locale_xterm; static uChar x11_button_state; static FRect* term; // current terminal geometry - static FPoint* term_pos; // terminal cursor position static FPoint* mouse; // mouse click position - static FPoint* cursor; // virtual print cursor + static int stdin_status_flags; static int stdin_no; static int stdout_no; @@ -168,8 +153,6 @@ class FTerm static char exit_message[8192]; static struct termios term_init; - static FOptiAttr::char_data term_attribute; - static FOptiAttr::char_data next_attribute; static fc::consoleCursorStyle console_cursor_style; static struct console_font_op screen_font; @@ -203,19 +186,6 @@ class FTerm uChar : 4; // padding bits } mod_key; - enum covered_state - { - non_covered, - half_covered, - fully_covered - }; - - enum character_type - { - overlapped_character, - covered_character - }; - protected: static bool NewFont; static bool VGAFont; @@ -224,34 +194,6 @@ class FTerm static uInt attr_without_color; static fc::encoding Encoding; - typedef struct - { - uInt xmin; - uInt xmax; - uInt trans_count; - } line_changes; - - typedef struct - { - int width; - int height; - int right_shadow; - int bottom_shadow; - int input_cursor_x; - int input_cursor_y; - int input_cursor_visible; - FWidget* widget; - line_changes* changes; - FOptiAttr::char_data* text; - bool visible; - } term_area; - - static term_area* vterm; // virtual terminal - static term_area* vdesktop; // virtual desktop - static term_area* last_area; // last used area - static term_area* active_area; // active area - term_area* vwin; // virtual window - private: // Disable copy constructor FTerm (const FTerm&); @@ -269,7 +211,7 @@ class FTerm static int setScreenFont (uChar*, uInt, uInt, uInt, bool = false); static int setUnicodeMap (struct unimapdesc*); static int getUnicodeMap (); - static int setLightBackgroundColors (bool); + static int setBlinkAsIntensity (bool); static void init_console(); static uInt getBaudRate (const struct termios*); static void init_consoleCharMap(); @@ -288,42 +230,14 @@ class FTerm static uInt charEncode (uInt, fc::encoding); static uInt cp437_to_unicode (uChar); static void signal_handler (int); + // Friend classes friend class FWidget; + friend class FVTerm; friend class FApplication; protected: static bool charEncodable (uInt); - void createArea (const FRect&, const FPoint&, FTerm::term_area*&); - void createArea (int, int, int, int, FTerm::term_area*&); - static void resizeArea (const FRect&, const FPoint&, FTerm::term_area*); - static void resizeArea (int, int, int, int, FTerm::term_area*); - static void removeArea (FTerm::term_area*&); - static void restoreVTerm (const FRect&); - static void restoreVTerm (int, int, int, int); - static FTerm::covered_state isCovered (const FPoint&, FTerm::term_area*); - static FTerm::covered_state isCovered (int, int, FTerm::term_area*); - static void updateVTerm (bool); - static void updateVTerm (FTerm::term_area*); - static bool updateVTermCursor (FTerm::term_area*); - static bool isInsideArea (int, int, FTerm::term_area*); - static void setAreaCursor (const FPoint&, bool, FTerm::term_area*); - static void setAreaCursor (int, int, bool, FTerm::term_area*); - static void getArea (const FPoint&, FTerm::term_area*); - static void getArea (int, int, FTerm::term_area*); - static void getArea (const FRect&, FTerm::term_area*); - static void getArea (int, int, int, int, FTerm::term_area*); - static void putArea (const FPoint&, FTerm::term_area*); - static void putArea (int, int, FTerm::term_area*); - static void scrollAreaForward (FTerm::term_area*); - static void scrollAreaReverse (FTerm::term_area*); - static void clearArea (FTerm::term_area*); - static FOptiAttr::char_data getCharacter (int, const FPoint&, FTerm*); - static FOptiAttr::char_data getCharacter (int, int, int, FTerm*); - static FOptiAttr::char_data getCoveredCharacter (const FPoint&, FTerm*); - static FOptiAttr::char_data getCoveredCharacter (int, int, FTerm*); - static FOptiAttr::char_data getOverlappedCharacter (const FPoint&, FTerm*); - static FOptiAttr::char_data getOverlappedCharacter (int, int, FTerm*); public: // Constructor @@ -332,12 +246,11 @@ class FTerm virtual ~FTerm(); virtual const char* getClassName() const; - FTerm::term_area* getVWin() const; static bool isKeyTimeout (timeval*, register long); static int parseKeyString (char*, int, timeval*); - bool& unprocessedInput() const; - int getLineNumber(); - int getColumnNumber(); + static bool& unprocessedInput(); + static int getLineNumber(); + static int getColumnNumber(); static FString getKeyName (int); static void getModifierKey(); @@ -367,18 +280,12 @@ class FTerm static bool isNewFont(); static bool setOldFont(); static bool setCursorOptimisation (bool); - static void setConsoleCursor (fc::consoleCursorStyle); + static void setConsoleCursor (fc::consoleCursorStyle, bool); + static char* moveCursor (int, int, int, int); + static char* enableCursor(); + static char* disableCursor(); static void getTermSize(); static void setTermSize (int, int); - void createVTerm (const FRect&); - void createVTerm (int, int); - static void resizeVTerm (const FRect&); - static void resizeVTerm (int, int); - static void putVTerm(); - static void updateTerminal (bool); - static void updateTerminal(); - static bool updateTerminalCursor(); - static bool isInsideTerminal (int, int); static void setKDECursor (fc::kdeKonsoleCursorShape); static FString getXTermFont(); static FString getXTermTitle(); @@ -400,8 +307,6 @@ class FTerm static void saveColorMap(); static void resetColorMap(); static void setPalette (short, int, int, int); - static short getTermForegroundColor(); - static short getTermBackgroundColor(); static int getMaxColor(); static void xtermMouse (bool); static void enableXTermMouse(); @@ -413,16 +318,10 @@ class FTerm static bool disableGpmMouse(); #endif // F_HAVE_LIBGPM - static void setTermXY (register int, register int); static void setBeep (int, int); static void resetBeep(); static void beep(); - static bool hideCursor (bool); - static bool hideCursor(); - static bool showCursor(); - static bool isHiddenCursor(); - static void setEncoding (std::string); static std::string getEncoding(); @@ -448,37 +347,6 @@ class FTerm static FString getAnswerbackMsg(); static FString getSecDA(); - static void printPosTerm (const FPoint&); - static void printPosTerm (register int, register int); - int printf (const wchar_t*, ...); - int printf (const char*, ...) - #if defined(__clang__) - __attribute__((__format__ (__printf__, 2, 3))) - #elif defined(__GNUC__) - __attribute__ ((format (printf, 2, 3))) - #endif - ; - int print (const std::wstring&); - int print (FTerm::term_area*, const std::wstring&); - int print (const wchar_t*); - int print (FTerm::term_area*, const wchar_t*); - int print (const char*); - int print (FTerm::term_area*, const char*); - int print (const std::string&); - int print (FTerm::term_area*, const std::string&); - int print (FString&); - int print (FTerm::term_area*, FString&); - int print (int); - int print (FTerm::term_area*, int); - static void newFontChanges (FOptiAttr::char_data*&); - static void charsetChanges (FOptiAttr::char_data*&); - static void appendCharacter (FOptiAttr::char_data*&); - static void appendAttributes (FOptiAttr::char_data*&); - static int appendLowerRight (FOptiAttr::char_data*&); - static void appendOutputBuffer (std::string&); - static void appendOutputBuffer (const char*); - static int appendOutputBuffer (int); - static void flush_out(); static int (*Fputchar)(int); // function pointer -> static function static void putstringf (const char*, ...) #if defined(__clang__) @@ -500,32 +368,6 @@ class FTerm inline const char* FTerm::getClassName() const { return "FTerm"; } -//---------------------------------------------------------------------- -inline FTerm::term_area* FTerm::getVWin() const -{ return vwin; } - -//---------------------------------------------------------------------- -inline bool& FTerm::unprocessedInput() const -{ return input_data_pending; } - -//---------------------------------------------------------------------- -inline int FTerm::getLineNumber() -{ - if ( term->getHeight() == 0 ) - getTermSize(); - - return term->getHeight(); -} - -//---------------------------------------------------------------------- -inline int FTerm::getColumnNumber() -{ - if ( term->getWidth() == 0 ) - getTermSize(); - - return term->getWidth(); -} - //---------------------------------------------------------------------- inline char* FTerm::getTermType() { return termtype; } @@ -554,10 +396,6 @@ inline bool FTerm::hasASCII() inline bool FTerm::isNewFont() { return NewFont; } -//---------------------------------------------------------------------- -inline bool FTerm::isHiddenCursor() -{ return hidden_cursor; } - //---------------------------------------------------------------------- inline bool FTerm::isMonochron() { return monochron; } @@ -620,23 +458,12 @@ inline bool FTerm::isTmuxTerm() //---------------------------------------------------------------------- inline bool FTerm::setCursorOptimisation (bool on) -{ - cursor_optimisation = on; - return cursor_optimisation; -} +{ return cursor_optimisation = (on) ? true : false; } //---------------------------------------------------------------------- inline bool FTerm::isRaw() { return raw_mode; } -//---------------------------------------------------------------------- -inline short FTerm::getTermForegroundColor() -{ return next_attribute.fg_color; } - -//---------------------------------------------------------------------- -inline short FTerm::getTermBackgroundColor() -{ return next_attribute.bg_color; } - //---------------------------------------------------------------------- inline int FTerm::getMaxColor() { return max_color; } @@ -649,7 +476,6 @@ inline void FTerm::enableXTermMouse() inline void FTerm::disableXTermMouse() { xtermMouse(false); } - #ifdef F_HAVE_LIBGPM //---------------------------------------------------------------------- inline bool FTerm::enableGpmMouse() @@ -658,17 +484,8 @@ inline bool FTerm::enableGpmMouse() //---------------------------------------------------------------------- inline bool FTerm::disableGpmMouse() { return gpmMouse(false); } - #endif // F_HAVE_LIBGPM -//---------------------------------------------------------------------- -inline bool FTerm::hideCursor() -{ return hideCursor(true); } - -//---------------------------------------------------------------------- -inline bool FTerm::showCursor() -{ return hideCursor(false); } - //---------------------------------------------------------------------- inline bool FTerm::setNonBlockingInput() { return setNonBlockingInput(true); } @@ -705,13 +522,5 @@ inline bool FTerm::unsetRawMode() inline bool FTerm::setCookedMode() { return setRawMode(false); } -//---------------------------------------------------------------------- -inline void FTerm::printPosTerm (const FPoint& pos) -{ printPosTerm (pos.getX(), pos.getY()); } - -//---------------------------------------------------------------------- -inline void FTerm::printPosTerm (register int x, register int y) -{ cursor->setPoint(x,y); } - #endif // _FTERM_H diff --git a/src/ftermcap.h b/src/ftermcap.h new file mode 100644 index 00000000..1a1b07c3 --- /dev/null +++ b/src/ftermcap.h @@ -0,0 +1,54 @@ +// File: ftermcap.h +// Provides: class FTermcap +// +// Standalone class +// ════════════════ +// +// ▕▔▔▔▔▔▔▔▔▔▔▏ +// ▕ FTermcap ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▏ + +#ifndef _FTERMCAP_H +#define _FTERMCAP_H + + +//---------------------------------------------------------------------- +// class FTermcap +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FTermcap +{ + public: + typedef struct + { + char* string; + char tname[3]; + } + tcap_map; + + private: + static tcap_map* tcap; + + public: + FTermcap() + { } + + ~FTermcap() + { } + + tcap_map* getTermcapMap() + { + return tcap; + } + + void setTermcapMap (tcap_map* t) + { + tcap = t; + } +}; +#pragma pack(pop) + +#endif // _FTERMCAP_H diff --git a/src/ftextview.cpp b/src/ftextview.cpp index b903cffd..6c8cdab5 100644 --- a/src/ftextview.cpp +++ b/src/ftextview.cpp @@ -146,7 +146,7 @@ void FTextView::drawText() uInt i, len; FString line; const wchar_t* line_str; - printPos (2, 2 - nf_offset + int(y)); + setPrintPos (2, 2 - nf_offset + int(y)); line = data[y+uInt(yoffset)].mid ( uInt(1 + xoffset) , uInt(getWidth() - nf_offset - 2) ); line_str = line.wc_str(); @@ -267,7 +267,7 @@ void FTextView::hide() for (int y=0; y < getHeight(); y++) { - printPos (1, 1 + y); + setPrintPos (1, 1 + y); print (blank); } @@ -921,7 +921,7 @@ void FTextView::clear() for (int y=0; y < getHeight() + nf_offset - 2; y++) { - printPos (2, 2 - nf_offset + y); + setPrintPos (2, 2 - nf_offset + y); print (blank); } diff --git a/src/ftextview.h b/src/ftextview.h index c75b9f8d..b1ef9a4c 100644 --- a/src/ftextview.h +++ b/src/ftextview.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/ftogglebutton.cpp b/src/ftogglebutton.cpp index e05ba934..e5d9afa7 100644 --- a/src/ftogglebutton.cpp +++ b/src/ftogglebutton.cpp @@ -219,7 +219,7 @@ void FToggleButton::drawLabel() if ( hotkeypos != -1 ) length--; - printPos (1 + label_offset_pos, 1); + setPrintPos (1 + label_offset_pos, 1); if ( isMonochron() ) setReverse(true); @@ -376,7 +376,7 @@ void FToggleButton::hide() blank = new char[size+1]; std::memset(blank, ' ', uLong(size)); blank[size] = '\0'; - printPos (1, 1); + setPrintPos (1, 1); print (blank); delete[] blank; } diff --git a/src/ftogglebutton.h b/src/ftogglebutton.h index 16c014cf..ef591cf5 100644 --- a/src/ftogglebutton.h +++ b/src/ftogglebutton.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/ftooltip.cpp b/src/ftooltip.cpp index 6b9371e1..a598acb0 100644 --- a/src/ftooltip.cpp +++ b/src/ftooltip.cpp @@ -123,7 +123,7 @@ void FToolTip::draw() for (int i=0; i < int(text_num_lines); i++) { - printPos (3, 2 + i); + setPrintPos (3, 2 + i); print(text_components[i]); } diff --git a/src/ftooltip.h b/src/ftooltip.h index 00373fbe..1fe66ee8 100644 --- a/src/ftooltip.h +++ b/src/ftooltip.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ diff --git a/src/fvterm.cpp b/src/fvterm.cpp new file mode 100644 index 00000000..08be22f8 --- /dev/null +++ b/src/fvterm.cpp @@ -0,0 +1,2103 @@ +// File: fvterm.cpp +// Provides: class FVTerm + +#include "fapp.h" +#include "fvterm.h" +#include "fwidget.h" +#include "fwindow.h" + +// global FVTerm object +static FVTerm* init_object = 0; + +// static class attributes +bool FVTerm::hidden_cursor; +bool FVTerm::terminal_update_pending; +bool FVTerm::force_terminal_update; +bool FVTerm::terminal_updates; +bool FVTerm::stop_terminal_updates; +bool FVTerm::vterm_updates; +int FVTerm::skipped_terminal_update = 0; +std::queue* FVTerm::output_buffer = 0; +FPoint* FVTerm::term_pos = 0; +FPoint* FVTerm::cursor = 0; +FVTerm::term_area* FVTerm::vterm = 0; +FVTerm::term_area* FVTerm::vdesktop = 0; +FVTerm::term_area* FVTerm::last_area = 0; +FVTerm::term_area* FVTerm::active_area = 0; +FTermcap::tcap_map* FVTerm::tcap = 0; +FOptiAttr::char_data FVTerm::term_attribute; +FOptiAttr::char_data FVTerm::next_attribute; + + +//---------------------------------------------------------------------- +// class FVTerm +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FVTerm::FVTerm (FVTerm* parent) + : FObject(parent) + , print_area(0) + , vwin(0) +{ + terminal_updates = false; + vterm_updates = true; + + if ( ! parent ) + { + init(); + } +} + +//---------------------------------------------------------------------- +FVTerm::~FVTerm() // destructor +{ + if ( init_object == this ) + { + finish(); + } +} + +//---------------------------------------------------------------------- +void FVTerm::init() +{ + init_object = this; + vterm = 0; + vdesktop = 0; + last_area = 0; + term_pos = new FPoint(-1,-1); + cursor = new FPoint(0,0); + output_buffer = new std::queue; + + // Preset to false + hidden_cursor = \ + terminal_update_pending = \ + force_terminal_update = \ + stop_terminal_updates = false; + + // term_attribute stores the current state of the terminal + term_attribute.code = '\0'; + term_attribute.fg_color = fc::Default; + term_attribute.bg_color = fc::Default; + term_attribute.bold = \ + term_attribute.dim = \ + term_attribute.italic = \ + term_attribute.underline = \ + term_attribute.blink = \ + term_attribute.reverse = \ + term_attribute.standout = \ + term_attribute.invisible = \ + term_attribute.protect = \ + term_attribute.crossed_out = \ + term_attribute.dbl_underline = \ + term_attribute.alt_charset = \ + term_attribute.pc_charset = \ + term_attribute.transparent = \ + term_attribute.trans_shadow = \ + term_attribute.inherit_bg = false; + + // next_attribute contains the state of the next printed character + std::memcpy (&next_attribute, &term_attribute, sizeof(FOptiAttr::char_data)); + + // receive the terminal capabilities + tcap = FTermcap().getTermcapMap(); + + // create virtual terminal + createVTerm (*term); + + // create virtual desktop area + FPoint shadow_size(0,0); + createArea (*term, shadow_size, vdesktop); + vdesktop->visible = true; + active_area = vdesktop; + + // Hide the input cursor + hideCursor(); +} + +//---------------------------------------------------------------------- +void FVTerm::finish() +{ + // Show the input cursor + showCursor(); + + if ( output_buffer ) + delete output_buffer; + + // remove virtual terminal + virtual desktop area + removeArea (vdesktop); + removeArea (vterm); + + if ( cursor ) + delete cursor; + + if ( term_pos ) + delete term_pos; +} + +//---------------------------------------------------------------------- +FVTerm::term_area* FVTerm::getPrintArea() +{ + // returns the print area of this object + if ( print_area ) + return print_area; + else + { + FVTerm* obj = static_cast(this); + FVTerm* p_obj = static_cast(obj->getParent()); + + while ( ! obj->vwin && p_obj ) + { + obj = p_obj; + p_obj = static_cast(p_obj->getParent()); + } + + if ( obj->vwin ) + { + print_area = obj->vwin; + return print_area; + } + } + + return vdesktop; +} + +//---------------------------------------------------------------------- +void FVTerm::createArea ( const FRect& r + , const FPoint& p + , FVTerm::term_area*& area ) +{ + createArea ( r.getWidth() + , r.getHeight() + , p.getX() + , p.getY() + , area ); +} + +//---------------------------------------------------------------------- +void FVTerm::createArea ( int width, int height + , int rsw, int bsh + , term_area*& area ) +{ + // initialize virtual window + area = new term_area; + + area->width = -1; + area->height = -1; + area->right_shadow = 0; + area->bottom_shadow = 0; + area->input_cursor_x = -1;; + area->input_cursor_y = -1;; + area->input_cursor_visible = false; + area->changes = 0; + area->text = 0; + area->visible = false; + area->widget = static_cast(this); + + resizeArea (width, height, rsw, bsh, area); +} + +//---------------------------------------------------------------------- +void FVTerm::resizeArea ( const FRect& r + , const FPoint& p + , FVTerm::term_area* area ) +{ + resizeArea ( r.getWidth() + , r.getHeight() + , p.getX() + , p.getY() + , area ); +} + +//---------------------------------------------------------------------- +void FVTerm::resizeArea ( int width, int height + , int rsw, int bsh + , term_area* area ) +{ + int area_size; + FOptiAttr::char_data default_char; + line_changes unchanged; + + if ( ! area ) + return; + + area_size = (width+rsw) * (height+bsh); + + if ( area->height + area->bottom_shadow != height + bsh ) + { + if ( area->changes != 0 ) + delete[] area->changes; + + if ( area->text != 0 ) + delete[] area->text; + + area->changes = new line_changes[height + bsh]; + area->text = new FOptiAttr::char_data[area_size]; + } + else if ( area->width + area->right_shadow != width + rsw ) + { + if ( area->text != 0 ) + delete[] area->text; + + area->text = new FOptiAttr::char_data[area_size]; + } + else + return; + + area->width = width; + area->height = height; + area->right_shadow = rsw; + area->bottom_shadow = bsh; + + default_char.code = ' '; + default_char.fg_color = fc::Default; + default_char.bg_color = fc::Default; + default_char.bold = 0; + default_char.dim = 0; + default_char.italic = 0; + default_char.underline = 0; + default_char.blink = 0; + default_char.reverse = 0; + default_char.standout = 0; + default_char.invisible = 0; + default_char.protect = 0; + default_char.crossed_out = 0; + default_char.dbl_underline = 0; + default_char.alt_charset = 0; + default_char.pc_charset = 0; + default_char.transparent = 0; + default_char.trans_shadow = 0; + default_char.inherit_bg = 0; + + std::fill_n (area->text, area_size, default_char); + + unchanged.xmin = uInt(width+rsw); + unchanged.xmax = 0; + unchanged.trans_count = 0; + + std::fill_n (area->changes, height+bsh, unchanged); +} + +//---------------------------------------------------------------------- +void FVTerm::removeArea (term_area*& area) +{ + // remove the virtual window + if ( area != 0 ) + { + if ( area->changes != 0 ) + { + delete[] area->changes; + area->changes = 0; + } + + if ( area->text != 0 ) + { + delete[] area->text; + area->text = 0; + } + + delete area; + area = 0; + } +} + +//---------------------------------------------------------------------- +void FVTerm::restoreVTerm (const FRect& box) +{ + restoreVTerm ( box.getX() + , box.getY() + , box.getWidth() + , box.getHeight() ); +} + +//---------------------------------------------------------------------- +void FVTerm::restoreVTerm (int x, int y, int w, int h) +{ + FOptiAttr::char_data* tc; // terminal character + FOptiAttr::char_data* sc; // shown character + FOptiAttr::char_data s_ch; // shadow character + FOptiAttr::char_data i_ch; // inherit background character + FWidget* widget; + + x--; + y--; + + if ( x < 0 ) + x = 0; + + if ( y < 0 ) + y = 0; + + if ( w < 0 || h < 0 ) + return; + + if ( x+w > vterm->width ) + w = vterm->width - x; + + if ( w < 0 ) + return; + + if ( y+h > vterm->height ) + h = vterm->height - y; + + if ( h < 0 ) + return; + + widget = static_cast(vterm->widget); + + for (register int ty=0; ty < h; ty++) + { + for (register int tx=0; tx < w; tx++) + { + tc = &vterm->text[(y+ty) * vterm->width + (x+tx)]; + sc = &vdesktop->text[(y+ty) * vdesktop->width + (x+tx)]; + + if ( widget->window_list && ! widget->window_list->empty() ) + { + FWidget::widgetList::const_iterator iter, end; + iter = widget->window_list->begin(); + end = widget->window_list->end(); + + while ( iter != end ) + { + term_area* win = (*iter)->getVWin(); + const FRect& geometry = (*iter)->getTermGeometryWithShadow(); + + // window visible and contains current character + if ( win && win->visible && geometry.contains(tx+x+1, ty+y+1) ) + { + FOptiAttr::char_data* tmp; + int win_x = (*iter)->getTermX() - 1; + int win_y = (*iter)->getTermY() - 1; + int line_len = win->width + win->right_shadow; + tmp = &win->text[(ty+y-win_y) * line_len + (tx+x-win_x)]; + + if ( ! tmp->transparent ) // current character not transparent + { + if ( tmp->trans_shadow ) // transparent shadow + { + // keep the current vterm character + std::memcpy (&s_ch, sc, sizeof(FOptiAttr::char_data)); + s_ch.fg_color = tmp->fg_color; + s_ch.bg_color = tmp->bg_color; + s_ch.reverse = false; + s_ch.standout = false; + + if ( s_ch.code == fc::LowerHalfBlock + || s_ch.code == fc::UpperHalfBlock + || s_ch.code == fc::LeftHalfBlock + || s_ch.code == fc::RightHalfBlock + || s_ch.code == fc::FullBlock ) + s_ch.code = ' '; + + sc = &s_ch; + } + else if ( tmp->inherit_bg ) + { + // add the covered background to this character + std::memcpy (&i_ch, tmp, sizeof(FOptiAttr::char_data)); + i_ch.bg_color = sc->bg_color; // last background color; + sc = &i_ch; + } + else // default + sc = tmp; + } + } + + ++iter; + } + } + + std::memcpy (tc, sc, sizeof(FOptiAttr::char_data)); + + if ( short(vterm->changes[y+ty].xmin) > x ) + vterm->changes[y+ty].xmin = uInt(x); + + if ( short(vterm->changes[y+ty].xmax) < x+w-1 ) + vterm->changes[y+ty].xmax = uInt(x+w-1); + } + } +} + +//---------------------------------------------------------------------- +FVTerm::covered_state FVTerm::isCovered ( const FPoint& pos + , FVTerm::term_area* area ) +{ + return isCovered (pos.getX(), pos.getY(), area); +} + +//---------------------------------------------------------------------- +FVTerm::covered_state FVTerm::isCovered ( int x, int y + , FVTerm::term_area* area ) +{ + bool found; + FVTerm::covered_state is_covered; + FWidget* w; + + if ( ! area ) + return non_covered; + + is_covered = non_covered; + found = bool(area == vdesktop); + x++; + y++; + + w = static_cast(area->widget); + + if ( w->window_list && ! w->window_list->empty() ) + { + FWidget::widgetList::const_iterator iter, end; + iter = w->window_list->begin(); + end = w->window_list->end(); + + while ( iter != end ) + { + term_area* win = (*iter)->getVWin(); + const FRect& geometry = (*iter)->getTermGeometryWithShadow(); + + if ( win && found + && (*iter)->isVisible() + && (*iter)->isShown() + && geometry.contains(x,y) ) + { + FOptiAttr::char_data* tmp; + int win_x = (*iter)->getTermX() - 1; + int win_y = (*iter)->getTermY() - 1; + int line_len = win->width + win->right_shadow; + tmp = &win->text[(y-win_y-1) * line_len + (x-win_x-1)]; + + if ( tmp->trans_shadow ) + { + is_covered = half_covered; + } + else if ( ! tmp->transparent ) + { + is_covered = fully_covered; + break; + } + } + + if ( area == win ) + found = true; + + ++iter; + } + } + + return is_covered; +} + +//---------------------------------------------------------------------- +void FVTerm::updateVTerm (bool on) +{ + vterm_updates = on; + + if ( on ) + updateVTerm (last_area); +} + +//---------------------------------------------------------------------- +void FVTerm::updateVTerm (FVTerm::term_area* area) +{ + int ax, ay, aw, ah, rsh, bsh, y_end, ol; + FOptiAttr::char_data* tc; // terminal character + FOptiAttr::char_data* ac; // area character + bool modified = false; + + if ( ! vterm_updates ) + { + last_area = area; + return; + } + + if ( ! area ) + return; + + if ( ! area->visible ) + return; + + ax = area->widget->getTermX() - 1; + ay = area->widget->getTermY() - 1; + aw = area->width; + ah = area->height; + rsh = area->right_shadow; + bsh = area->bottom_shadow; + ol = 0; // outside left + + if ( ax < 0 ) + { + ol = std::abs(ax); + ax = 0; + } + + if ( ah + bsh + ay > vterm->height ) + y_end = vterm->height - ay; + else + y_end = ah + bsh; + + for (register int y=0; y < y_end; y++) // line loop + { + int line_xmin = int(area->changes[y].xmin); + int line_xmax = int(area->changes[y].xmax); + + if ( line_xmin <= line_xmax ) + { + int _xmin, _xmax; + + if ( ax == 0 ) + line_xmin = ol; + + if ( aw + rsh + ax - ol >= vterm->width ) + line_xmax = vterm->width + ol - ax - 1; + + if ( ax + line_xmin >= vterm->width ) + continue; + + for (register int x=line_xmin; x <= line_xmax; x++) // column loop + { + int gx, gy, line_len; + FVTerm::covered_state is_covered; + // global terminal positions + gx = ax + x; + gy = ay + y; + + if ( gx < 0 || gy < 0 ) + continue; + + line_len = aw + rsh; + ac = &area->text[y * line_len + x]; + tc = &vterm->text[gy * vterm->width + gx - ol]; + is_covered = isCovered(gx-ol, gy, area); // get covered state + + if ( is_covered != fully_covered ) + { + if ( is_covered == half_covered ) + { + // add the overlapping color to this character + FOptiAttr::char_data ch, oc; + std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); + oc = getOverlappedCharacter (gx+1 - ol, gy+1, area->widget); + ch.fg_color = oc.fg_color; + ch.bg_color = oc.bg_color; + ch.reverse = false; + ch.standout = false; + + if ( ch.code == fc::LowerHalfBlock + || ch.code == fc::UpperHalfBlock + || ch.code == fc::LeftHalfBlock + || ch.code == fc::RightHalfBlock + || ch.code == fc::FullBlock ) + ch.code = ' '; + + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else if ( ac->transparent ) // transparent + { + // restore one character on vterm + FOptiAttr::char_data ch; + ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else // not transparent + { + if ( ac->trans_shadow ) // transparent shadow + { + // get covered character + add the current color + FOptiAttr::char_data ch; + ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); + ch.fg_color = ac->fg_color; + ch.bg_color = ac->bg_color; + ch.reverse = false; + ch.standout = false; + + if ( ch.code == fc::LowerHalfBlock + || ch.code == fc::UpperHalfBlock + || ch.code == fc::LeftHalfBlock + || ch.code == fc::RightHalfBlock + || ch.code == fc::FullBlock ) + ch.code = ' '; + + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else if ( ac->inherit_bg ) + { + // add the covered background to this character + FOptiAttr::char_data ch, cc; + std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); + cc = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); + ch.bg_color = cc.bg_color; + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else // default + std::memcpy (tc, ac, sizeof(FOptiAttr::char_data)); + } + + modified = true; + } + else if ( ! modified ) + line_xmin++; // don't update covered character + } + + _xmin = ax + line_xmin - ol; + _xmax = ax + line_xmax; + + if ( _xmin < short(vterm->changes[ay+y].xmin) ) + vterm->changes[ay+y].xmin = uInt(_xmin); + + if ( _xmax >= vterm->width ) + _xmax = vterm->width - 1; + + if ( _xmax > short(vterm->changes[ay+y].xmax) ) + vterm->changes[ay+y].xmax = uInt(_xmax); + + area->changes[y].xmin = uInt(aw + rsh); + area->changes[y].xmax = 0; + } + } + + updateVTermCursor(area); +} + +//---------------------------------------------------------------------- +bool FVTerm::updateVTermCursor (FVTerm::term_area* area) +{ + if ( ! area ) + return false; + + if ( area != active_area ) + return false; + + if ( ! area->visible ) + return false; + + if ( area->input_cursor_visible ) + { + int cx, cy, ax, ay, x, y; + // cursor position + cx = area->input_cursor_x; + cy = area->input_cursor_y; + // widget position + ax = area->widget->getTermX() - 1; + ay = area->widget->getTermY() - 1; + // area position + x = ax + cx; + y = ay + cy; + + if ( isInsideArea(cx, cy, area) + && isInsideTerminal(x+1, y+1) + && isCovered(x, y, area) == non_covered ) + { + vterm->input_cursor_x = x; + vterm->input_cursor_y = y; + vterm->input_cursor_visible = true; + return true; + } + } + + vterm->input_cursor_visible = false; + return false; +} + +//---------------------------------------------------------------------- +bool FVTerm::isInsideArea (int x, int y, FVTerm::term_area* area) +{ + // Check whether the coordinates are within the area + int ax, ay, aw, ah; + ax = 0; + ay = 0; + aw = area->width; + ah = area->height; + FRect area_geometry(ax, ay, aw, ah); + + if ( area_geometry.contains(x,y) ) + return true; + else + return false; +} + +//---------------------------------------------------------------------- +void FVTerm::setAreaCursor ( const FPoint& pos + , bool visible + , FVTerm::term_area* area ) +{ + setAreaCursor (pos.getX(), pos.getY(), visible, area); +} + +//---------------------------------------------------------------------- +void FVTerm::setAreaCursor ( int x, int y + , bool visible + , FVTerm::term_area* area ) +{ + if ( ! area ) + return; + + area->input_cursor_x = x - 1; + area->input_cursor_y = y - 1; + area->input_cursor_visible = visible; + updateVTerm (area); +} + +//---------------------------------------------------------------------- +void FVTerm::getArea (const FPoint& pos, FVTerm::term_area* area) +{ + return getArea (pos.getX(), pos.getY(), area); +} + +//---------------------------------------------------------------------- +void FVTerm::getArea (int ax, int ay, FVTerm::term_area* area) +{ + // Copies a block from the virtual terminal position to the given area + int y_end; + int length; + FOptiAttr::char_data* tc; // terminal character + FOptiAttr::char_data* ac; // area character + + if ( ! area ) + return; + + ax--; + ay--; + + if ( area->height+ay > vterm->height ) + y_end = area->height - ay; + else + y_end = area->height; + + if ( area->width+ax > vterm->width ) + length = vterm->width - ax; + else + length = area->width; + + for (int y=0; y < y_end; y++) // line loop + { + tc = &vterm->text[(ay+y) * vterm->width + ax]; + ac = &area->text[y * area->width]; + std::memcpy (ac, tc, sizeof(FOptiAttr::char_data) * unsigned(length)); + + if ( short(area->changes[y].xmin) > 0 ) + area->changes[y].xmin = 0; + + if ( short(area->changes[y].xmax) < length-1 ) + area->changes[y].xmax = uInt(length-1); + } +} + +//---------------------------------------------------------------------- +void FVTerm::getArea (const FRect& box, FVTerm::term_area* area) +{ + getArea ( box.getX() + , box.getY() + , box.getWidth() + , box.getHeight() + , area ); +} + +//---------------------------------------------------------------------- +void FVTerm::getArea (int x, int y, int w, int h, FVTerm::term_area* area) +{ + // Copies a block from the virtual terminal rectangle to the given area + int y_end, length, dx, dy; + FOptiAttr::char_data* tc; // terminal character + FOptiAttr::char_data* ac; // area character + + if ( ! area ) + return; + + dx = x - area->widget->getTermX(); + dy = y - area->widget->getTermY(); + + if ( x < 0 || y < 0 ) + return; + + if ( y-1+h > vterm->height ) + y_end = vterm->height - y + 1; + else + y_end = h - 1; + + if ( x-1+w > vterm->width ) + length = vterm->width - x + 1; + else + length = w; + + if ( length < 1 ) + return; + + for (int _y=0; _y < y_end; _y++) // line loop + { + int line_len = area->width + area->right_shadow; + tc = &vterm->text[(y+_y-1) * vterm->width + x-1]; + ac = &area->text[(dy+_y) * line_len + dx]; + std::memcpy (ac, tc, sizeof(FOptiAttr::char_data) * unsigned(length)); + + if ( short(area->changes[dy+_y].xmin) > dx ) + area->changes[dy+_y].xmin = uInt(dx); + + if ( short(area->changes[dy+_y].xmax) < dx+length-1 ) + area->changes[dy+_y].xmax = uInt(dx+length-1); + } +} + +//---------------------------------------------------------------------- +void FVTerm::putArea (const FPoint& pos, FVTerm::term_area* area) +{ + // Copies the given area block to the virtual terminal position + if ( ! area ) + return; + + if ( ! area->visible ) + return; + + putArea (pos.getX(), pos.getY(), area); +} + +//---------------------------------------------------------------------- +void FVTerm::putArea (int ax, int ay, FVTerm::term_area* area) +{ + // Copies the given area block to the virtual terminal position + int aw, ah, rsh, bsh, y_end, length, ol; + FOptiAttr::char_data* tc; // terminal character + FOptiAttr::char_data* ac; // area character + + if ( ! area ) + return; + + if ( ! area->visible ) + return; + + ax--; + ay--; + aw = area->width; + ah = area->height; + rsh = area->right_shadow; + bsh = area->bottom_shadow; + ol = 0; // outside left + + if ( ax < 0 ) + { + ol = std::abs(ax); + ax = 0; + } + + if ( ay + ah + bsh > vterm->height ) + y_end = vterm->height - ay; + else + y_end = ah + bsh; + + if ( aw + rsh - ol + ax > vterm->width ) + length = vterm->width - ax; + else + length = aw + rsh - ol; + + if ( length < 1 ) + return; + + for (register int y=0; y < y_end; y++) // line loop + { + int line_len = aw + rsh; + + if ( area->changes[y].trans_count == 0 ) + { + // Line has only covered characters + tc = &vterm->text[(ay+y) * vterm->width + ax]; + ac = &area->text[y * line_len + ol]; + std::memcpy (tc, ac, sizeof(FOptiAttr::char_data) * unsigned(length)); + } + else + { + // Line has one or more transparent characters + for (register int x=0; x < length; x++) // column loop + { + tc = &vterm->text[(ay+y) * vterm->width + (ax+x)]; + ac = &area->text[y * line_len + ol + x]; + + if ( ac->transparent ) // transparent + { + // restore one character on vterm + FOptiAttr::char_data ch; + ch = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else // not transparent + { + if ( ac->trans_shadow ) // transparent shadow + { + // get covered character + add the current color + FOptiAttr::char_data ch; + ch = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); + ch.fg_color = ac->fg_color; + ch.bg_color = ac->bg_color; + ch.reverse = false; + ch.standout = false; + + if ( ch.code == fc::LowerHalfBlock + || ch.code == fc::UpperHalfBlock + || ch.code == fc::LeftHalfBlock + || ch.code == fc::RightHalfBlock + || ch.code == fc::FullBlock ) + ch.code = ' '; + + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else if ( ac->inherit_bg ) + { + // add the covered background to this character + FOptiAttr::char_data ch, cc; + std::memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); + cc = getCoveredCharacter (ax+x+1, ay+y+1, area->widget); + ch.bg_color = cc.bg_color; + std::memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); + } + else // default + std::memcpy (tc, ac, sizeof(FOptiAttr::char_data)); + } + } + } + + if ( ax < short(vterm->changes[ay+y].xmin) ) + vterm->changes[ay+y].xmin = uInt(ax); + + if ( ax+length-1 > short(vterm->changes[ay+y].xmax) ) + vterm->changes[ay+y].xmax = uInt(ax+length-1); + } +} + +//---------------------------------------------------------------------- +void FVTerm::scrollAreaForward (FVTerm::term_area* area) +{ + 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 FVTerm::scrollAreaReverse (FVTerm::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 FVTerm::clearArea (FVTerm::term_area* area) +{ + FOptiAttr::char_data nc; // next character + int total_width; + uInt w; + + // clear with the current attributes and space characters + std::memcpy (&nc, &next_attribute, sizeof(FOptiAttr::char_data)); + nc.code = ' '; + + if ( ! area ) + return; + + total_width = area->width + area->right_shadow; + w = uInt(total_width); + + if ( area->right_shadow == 0 ) + { + int area_size = area->width * area->height; + std::fill_n (area->text, area_size, nc); + } + else + { + 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, nc); + std::fill_n (&area->text[pos+area->width], area->right_shadow, t_char); + } + + for (int y=0; y < area->bottom_shadow; y++) + { + int pos = total_width * (y + area->height); + std::fill_n (&area->text[pos], total_width, t_char); + } + } + + for (int i=0; i < area->height; i++) + { + + area->changes[i].xmin = 0; + area->changes[i].xmax = w - 1; + + 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); + else + area->changes[i].trans_count = 0; + } + + for (int i=0; i < area->bottom_shadow; i++) + { + int y = area->height + i; + area->changes[y].xmin = 0; + area->changes[y].xmax = w - 1; + area->changes[y].trans_count = w; + } + + updateVTerm (area); +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getCharacter ( int type + , const FPoint& pos + , FVTerm* obj ) +{ + return getCharacter (type, pos.getX(), pos.getY(), obj); +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getCharacter ( int char_type + , int x + , int y + , FVTerm* obj ) +{ + // get the overlapped or the covered character for a position + int xx,yy; + FOptiAttr::char_data* cc; // covered character + FOptiAttr::char_data s_ch; // shadow character + FOptiAttr::char_data i_ch; // inherit background character + FWidget* w; + + x--; + y--; + xx = x; + yy = y; + + if ( xx < 0 ) + xx = 0; + + if ( yy < 0 ) + yy = 0; + + if ( xx >= vterm->width ) + xx = vterm->width - 1; + + if ( yy >= vterm->height ) + yy = vterm->height - 1; + + cc = &vdesktop->text[yy * vdesktop->width + xx]; + w = static_cast(obj); + + if ( w->window_list && ! w->window_list->empty() ) + { + FWidget::widgetList::const_iterator iter, end; + // get the window layer of this object + int layer = FWindow::getWindowLayer(w); + iter = w->window_list->begin(); + end = w->window_list->end(); + + while ( iter != end ) + { + bool significant_char; + + // char_type can be "overlapped_character" + // or "covered_character" + if ( char_type == covered_character ) + significant_char = bool(layer >= FWindow::getWindowLayer(*iter)); + else + significant_char = bool(layer < FWindow::getWindowLayer(*iter)); + + if ( obj && *iter != obj && significant_char ) + { + term_area* win = (*iter)->getVWin(); + const FRect& geometry = (*iter)->getTermGeometryWithShadow(); + + // window visible and contains current character + if ( win && win->visible && geometry.contains(x+1,y+1) ) + { + FOptiAttr::char_data* tmp; + int win_x = (*iter)->getTermX() - 1; + int win_y = (*iter)->getTermY() - 1; + int line_len = win->width + win->right_shadow; + tmp = &win->text[(y-win_y) * line_len + (x-win_x)]; + + // current character not transparent + if ( ! tmp->transparent ) + { + if ( tmp->trans_shadow ) // transparent shadow + { + // keep the current vterm character + std::memcpy (&s_ch, cc, sizeof(FOptiAttr::char_data)); + s_ch.fg_color = tmp->fg_color; + s_ch.bg_color = tmp->bg_color; + s_ch.reverse = false; + s_ch.standout = false; + cc = &s_ch; + } + else if ( tmp->inherit_bg ) + { + // add the covered background to this character + std::memcpy (&i_ch, tmp, sizeof(FOptiAttr::char_data)); + i_ch.bg_color = cc->bg_color; // last background color + cc = &i_ch; + } + else // default + cc = tmp; + } + } + } + else if ( char_type == covered_character ) + break; + + ++iter; + } + } + + return *cc; +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getCoveredCharacter ( int x + , int y + , FVTerm* obj) +{ + return getCharacter (covered_character, x, y, obj); +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getCoveredCharacter ( const FPoint& pos + , FVTerm* obj ) +{ + return getCharacter (covered_character, pos.getX(), pos.getY(), obj); +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getOverlappedCharacter ( int x + , int y + , FVTerm* obj) +{ + return getCharacter (overlapped_character, x, y, obj); +} + +//---------------------------------------------------------------------- +FOptiAttr::char_data FVTerm::getOverlappedCharacter ( const FPoint& pos + , FVTerm* obj ) +{ + return getCharacter (overlapped_character, pos.getX(), pos.getY(), obj); +} + +//---------------------------------------------------------------------- +void FVTerm::setTermXY (register int x, register int y) +{ + // sets the hardware cursor to the given (x,y) position + int term_x, term_y, term_width, term_height; + char* move_str; + + if ( term_pos->getX() == x && term_pos->getY() == y ) + return; + + term_width = term->getWidth(); + term_height = term->getHeight(); + + if ( x >= term_width ) + { + y += x / term_width; + x %= term_width; + } + + if ( term_pos->getY() >= term_height ) + term_pos->setY(term_height - 1); + + if ( y >= term_height ) + y = term_height - 1; + + term_x = term_pos->getX(); + term_y = term_pos->getY(); + + move_str = moveCursor (term_x, term_y, x, y); + + if ( move_str ) + appendOutputBuffer(move_str); + + flush_out(); + term_pos->setPoint(x,y); +} + +//---------------------------------------------------------------------- +bool FVTerm::hideCursor (bool on) +{ + if ( on == hidden_cursor ) + return hidden_cursor; + + if ( on ) + { + char* hide_str = disableCursor(); + + if ( hide_str ) + appendOutputBuffer (hide_str); + + hidden_cursor = true; // global + } + else + { + char* show_str = enableCursor(); + + if ( show_str ) + appendOutputBuffer (show_str); + + hidden_cursor = false; + } + + flush_out(); + + if ( ! hidden_cursor && isLinuxTerm() ) + setConsoleCursor (console_cursor_style, false); + + return hidden_cursor; +} + +//---------------------------------------------------------------------- +void FVTerm::createVTerm (const FRect& r) +{ + // initialize virtual terminal + const FPoint shadow(0,0); + createArea (r, shadow, vterm); +} + +//---------------------------------------------------------------------- +void FVTerm::createVTerm (int width, int height) +{ + // initialize virtual terminal + createArea (width, height, 0, 0, vterm); +} + +//---------------------------------------------------------------------- +void FVTerm::resizeVTerm (const FRect& r) +{ + const FPoint shadow(0,0); + resizeArea (r, shadow, vterm); +} + +//---------------------------------------------------------------------- +void FVTerm::resizeVTerm (int width, int height) +{ + resizeArea (width, height, 0, 0, vterm); +} + +//---------------------------------------------------------------------- +void FVTerm::putVTerm() +{ + for (int i=0; i < vterm->height; i++) + { + vterm->changes[i].xmin = 0; + vterm->changes[i].xmax = uInt(vterm->width - 1); + } + + updateTerminal(); +} + +//---------------------------------------------------------------------- +void FVTerm::updateTerminal (bool on) +{ + stop_terminal_updates = bool(! on); + + if ( on ) + updateTerminal(); +} + +//---------------------------------------------------------------------- +void FVTerm::updateTerminal() +{ + term_area* vt; + int term_width, term_height; + + if ( stop_terminal_updates + || static_cast(init_object)->isQuit() ) + return; + + if ( ! force_terminal_update ) + { + if ( ! terminal_updates ) + return; + + if ( input_data_pending ) + { + terminal_update_pending = true; + return; + } + } + + vt = vterm; + term_width = vt->width - 1; + term_height = vt->height - 1; + + for (register uInt y=0; y < uInt(vt->height); y++) + { + uInt change_xmax = vt->changes[y].xmax; + + if ( vt->changes[y].xmin <= vt->changes[y].xmax ) + { + uInt change_xmin = vt->changes[y].xmin; + setTermXY (int(change_xmin), int(y)); + + for ( register uInt x=change_xmin; + x <= change_xmax; + x++ ) + { + FOptiAttr::char_data* print_char; + print_char = &vt->text[y * uInt(vt->width) + x]; + + if ( term_pos->getX() == term_width + && term_pos->getY() == term_height ) + appendLowerRight (print_char); + else + appendCharacter (print_char); + + term_pos->x_ref()++; + } + + vt->changes[y].xmin = uInt(vt->width); + vt->changes[y].xmax = 0; + } + + // cursor wrap + if ( term_pos->getX() > term_width ) + { + if ( term_pos->getY() == term_height ) + term_pos->x_ref()--; + else + { + if ( eat_nl_glitch ) + { + term_pos->setPoint(-1,-1); + } + else if ( automatic_right_margin ) + { + term_pos->setX(0); + term_pos->y_ref()++; + } + else + term_pos->x_ref()--; + } + } + } + + // sets the new input cursor position + updateTerminalCursor(); +} + +//---------------------------------------------------------------------- +bool FVTerm::updateTerminalCursor() +{ + // updates the input cursor visibility and the position + if ( vterm && vterm->input_cursor_visible ) + { + int x = vterm->input_cursor_x; + int y = vterm->input_cursor_y; + + if ( isInsideTerminal(x+1, y+1) ) + { + setTermXY (x,y); + showCursor(); + return true; + } + } + else + hideCursor(); + + return false; +} + +//---------------------------------------------------------------------- +void FVTerm::processTerminalUpdate() +{ + const int max_skip = 8; + + if ( terminal_update_pending ) + { + if ( ! unprocessedInput() ) + { + updateTerminal(); + terminal_update_pending = false; + skipped_terminal_update = 0; + } + else if ( skipped_terminal_update > max_skip ) + { + force_terminal_update = true; + updateTerminal(); + force_terminal_update = false; + terminal_update_pending = false; + skipped_terminal_update = 0; + } + else + skipped_terminal_update++; + } +} + +//---------------------------------------------------------------------- +bool FVTerm::isInsideTerminal (int x, int y) +{ + // Check whether the coordinates are within the virtual terminal + if ( term->contains(x,y) ) + return true; + else + return false; +} + +//---------------------------------------------------------------------- +FPoint* FVTerm::getPrintPos() const +{ + return cursor; +} + +//---------------------------------------------------------------------- +int FVTerm::printf (const wchar_t* format, ...) +{ + assert ( format != 0 ); + const int buf_size = 1024; + wchar_t buffer[buf_size]; + va_list args; + + va_start (args, format); + std::vswprintf (buffer, buf_size, format, args); + va_end (args); + + FString str(buffer); + return print(str); +} + +//---------------------------------------------------------------------- +int FVTerm::printf (const char* format, ...) +{ + assert ( format != 0 ); + int len; + char buf[512]; + char* buffer; + va_list args; + + buffer = buf; + va_start (args, format); + len = std::vsnprintf (buffer, sizeof(buf), format, args); + va_end (args); + + if ( len >= int(sizeof(buf)) ) + { + buffer = new char[len+1](); + va_start (args, format); + std::vsnprintf (buffer, uLong(len+1), format, args); + va_end (args); + } + + FString str(buffer); + int ret = print(str); + + if ( buffer != buf ) + delete[] buffer; + + return ret; +} + +//---------------------------------------------------------------------- +int FVTerm::print (const std::wstring& s) +{ + assert ( ! s.empty() ); + return print (FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, const std::wstring& s) +{ + assert ( area != 0 ); + assert ( ! s.empty() ); + return print (area, FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (const wchar_t* s) +{ + assert ( s != 0 ); + return print (FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, const wchar_t* s) +{ + assert ( area != 0 ); + assert ( s != 0 ); + return print (area, FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (const char* s) +{ + assert ( s != 0 ); + FString str(s); + return print(str); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, const char* s) +{ + assert ( area != 0 ); + assert ( s != 0 ); + FString str(s); + return print(area, str); +} + +//---------------------------------------------------------------------- +int FVTerm::print (const std::string& s) +{ + assert ( ! s.empty() ); + return print (FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, const std::string& s) +{ + assert ( area != 0 ); + assert ( ! s.empty() ); + return print (area, FString(s)); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FString& s) +{ + assert ( ! s.isNull() ); + term_area* area; + FWidget* w; + w = static_cast(this); + area = w->getPrintArea(); + + if ( ! area ) + { + FWidget* root = w->getRootWidget(); + area = vdesktop; + + if ( ! root ) + return -1; + } + + return print (area, s); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, FString& s) +{ + assert ( ! s.isNull() ); + register int len = 0; + const wchar_t* p; + FWidget* window; + + if ( ! area ) + return -1; + + window = area->widget; + + if ( ! window ) + return -1; + + p = s.wc_str(); + + if ( p ) + { + while ( *p ) + { + int rsh, bsh; + + switch ( *p ) + { + case '\n': + cursor->y_ref()++; + + case '\r': + cursor->x_ref() = 1; + break; + + case '\t': + cursor->x_ref() = short ( uInt(cursor->x_ref()) + + tabstop + - uInt(cursor->x_ref()) + + 1 + % tabstop ); + break; + + case '\b': + cursor->x_ref()--; + break; + + case '\a': + beep(); + break; + + default: + { + short x = short(cursor->getX()); + short y = short(cursor->getY()); + + FOptiAttr::char_data nc; // next character + nc.code = *p; + nc.fg_color = next_attribute.fg_color; + nc.bg_color = next_attribute.bg_color; + nc.bold = next_attribute.bold; + nc.dim = next_attribute.dim; + nc.italic = next_attribute.italic; + nc.underline = next_attribute.underline; + nc.blink = next_attribute.blink; + nc.reverse = next_attribute.reverse; + nc.standout = next_attribute.standout; + nc.invisible = next_attribute.invisible; + nc.protect = next_attribute.protect; + nc.crossed_out = next_attribute.crossed_out; + nc.dbl_underline = next_attribute.dbl_underline; + nc.alt_charset = next_attribute.alt_charset; + nc.pc_charset = next_attribute.pc_charset; + nc.transparent = next_attribute.transparent; + nc.trans_shadow = next_attribute.trans_shadow; + nc.inherit_bg = next_attribute.inherit_bg; + + int ax = x - window->getTermX(); + int ay = y - window->getTermY(); + + if ( area + && ax >= 0 && ay >= 0 + && ax < area->width + area->right_shadow + && ay < area->height + area->bottom_shadow ) + { + FOptiAttr::char_data* ac; // area character + int line_len = area->width + area->right_shadow; + ac = &area->text[ay * line_len + ax]; + + if ( *ac != nc ) // compare with an overloaded operator + { + if ( ( ! ac->transparent && nc.transparent ) + || ( ! ac->trans_shadow && nc.trans_shadow ) + || ( ! ac->inherit_bg && nc.inherit_bg ) ) + { + // add one transparent character form line + area->changes[ay].trans_count++; + } + else if ( ( ac->transparent && ! nc.transparent ) + || ( ac->trans_shadow && ! nc.trans_shadow ) + || ( ac->inherit_bg && ! nc.inherit_bg ) ) + { + // remove one transparent character from line + area->changes[ay].trans_count--; + } + + // copy character to area + std::memcpy (ac, &nc, sizeof(nc)); + + if ( ax < short(area->changes[ay].xmin) ) + area->changes[ay].xmin = uInt(ax); + + if ( ax > short(area->changes[ay].xmax) ) + area->changes[ay].xmax = uInt(ax); + } + } + + cursor->x_ref()++; + } + } + + rsh = area->right_shadow; + bsh = area->bottom_shadow; + const FRect& area_geometry = window->getTermGeometry(); + + if ( cursor->x_ref() > area_geometry.getX2()+rsh ) + { + cursor->x_ref() = short(window->getTermX()); + cursor->y_ref()++; + } + + if ( cursor->y_ref() > area_geometry.getY2()+bsh ) + { + cursor->y_ref()--; + break; + } + + p++; + len++; + } // end of while + + updateVTerm (area); + } + + return len; +} + +//---------------------------------------------------------------------- +int FVTerm::print (register int c) +{ + term_area* area; + FWidget* w; + w = static_cast(this); + area = w->getPrintArea(); + + if ( ! area ) + { + FWidget* root = w->getRootWidget(); + area = vdesktop; + + if ( ! root ) + return -1; + } + + return print (area, c); +} + +//---------------------------------------------------------------------- +int FVTerm::print (FVTerm::term_area* area, register int c) +{ + FOptiAttr::char_data nc; // next character + FWidget* window; + int rsh, bsh, ax, ay; + short x, y; + + if ( ! area ) + return -1; + + nc.code = c; + nc.fg_color = next_attribute.fg_color; + nc.bg_color = next_attribute.bg_color; + nc.bold = next_attribute.bold; + nc.dim = next_attribute.dim; + nc.italic = next_attribute.italic; + nc.underline = next_attribute.underline; + nc.blink = next_attribute.blink; + nc.reverse = next_attribute.reverse; + nc.standout = next_attribute.standout; + nc.invisible = next_attribute.invisible; + nc.protect = next_attribute.protect; + nc.crossed_out = next_attribute.crossed_out; + nc.dbl_underline = next_attribute.dbl_underline; + nc.alt_charset = next_attribute.alt_charset; + nc.pc_charset = next_attribute.pc_charset; + nc.transparent = next_attribute.transparent; + nc.trans_shadow = next_attribute.trans_shadow; + nc.inherit_bg = next_attribute.inherit_bg; + + x = short(cursor->getX()); + y = short(cursor->getY()); + window = area->widget; + + if ( ! window ) + return -1; + + ax = x - window->getTermX(); + ay = y - window->getTermY(); + + if ( ax >= 0 && ay >= 0 + && ax < area->width + area->right_shadow + && ay < area->height + area->bottom_shadow ) + { + FOptiAttr::char_data* ac; // area character + int line_len = area->width + area->right_shadow; + ac = &area->text[ay * line_len + ax]; + + if ( *ac != nc ) // compare with an overloaded operator + { + if ( ( ! ac->transparent && nc.transparent ) + || ( ! ac->trans_shadow && nc.trans_shadow ) + || ( ! ac->inherit_bg && nc.inherit_bg ) ) + { + // add one transparent character form line + area->changes[ay].trans_count++; + } + + if ( ( ac->transparent && ! nc.transparent ) + || ( ac->trans_shadow && ! nc.trans_shadow ) + || ( ac->inherit_bg && ! nc.inherit_bg ) ) + { + // remove one transparent character from line + area->changes[ay].trans_count--; + } + + // copy character to area + std::memcpy (ac, &nc, sizeof(nc)); + + if ( ax < short(area->changes[ay].xmin) ) + area->changes[ay].xmin = uInt(ax); + + if ( ax > short(area->changes[ay].xmax) ) + area->changes[ay].xmax = uInt(ax); + } + } + + cursor->x_ref()++; + rsh = area->right_shadow; + bsh = area->bottom_shadow; + const FRect& area_geometry = window->getTermGeometry(); + + if ( cursor->x_ref() > area_geometry.getX2()+rsh ) + { + cursor->x_ref() = short(window->getTermX()); + cursor->y_ref()++; + } + + if ( cursor->y_ref() > area_geometry.getY2()+bsh ) + { + cursor->y_ref()--; + updateVTerm (area); + return -1; + } + + updateVTerm (area); + return 1; +} + +//---------------------------------------------------------------------- +inline void FVTerm::newFontChanges (FOptiAttr::char_data*& next_char) +{ + // NewFont special cases + if ( NewFont ) + { + switch ( next_char->code ) + { + case fc::LowerHalfBlock: + next_char->code = fc::UpperHalfBlock; + // fall through + case fc::NF_rev_left_arrow2: + case fc::NF_rev_right_arrow2: + case fc::NF_rev_border_corner_upper_right: + case fc::NF_rev_border_line_right: + case fc::NF_rev_border_line_vertical_left: + case fc::NF_rev_border_corner_lower_right: + case fc::NF_rev_up_arrow2: + case fc::NF_rev_down_arrow2: + case fc::NF_rev_up_arrow1: + case fc::NF_rev_down_arrow1: + case fc::NF_rev_left_arrow1: + case fc::NF_rev_right_arrow1: + case fc::NF_rev_menu_button1: + case fc::NF_rev_menu_button2: + case fc::NF_rev_up_pointing_triangle1: + case fc::NF_rev_down_pointing_triangle1: + case fc::NF_rev_up_pointing_triangle2: + case fc::NF_rev_down_pointing_triangle2: + case fc::NF_rev_menu_button3: + case fc::NF_rev_border_line_right_and_left: + // swap foreground and background color + std::swap (next_char->fg_color, next_char->bg_color); + break; + + default: + break; + } + } +} + +//---------------------------------------------------------------------- +inline void FVTerm::charsetChanges (FOptiAttr::char_data*& next_char) +{ + if ( Encoding == fc::UTF8 ) + return; + + uInt code = uInt(next_char->code); + uInt ch = charEncode(code); + + if ( ch != code ) + { + if ( ch == 0 ) + { + next_char->code = int(charEncode(code, fc::ASCII)); + return; + } + + next_char->code = int(ch); + + if ( Encoding == fc::VT100 ) + next_char->alt_charset = true; + else if ( Encoding == fc::PC ) + { + next_char->pc_charset = true; + + if ( isXTerminal() && utf8_console && ch < 0x20 ) // Character 0x00..0x1f + next_char->code = int(charEncode(code, fc::ASCII)); + } + } +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendCharacter (FOptiAttr::char_data*& next_char) +{ + newFontChanges (next_char); + charsetChanges (next_char); + + appendAttributes (next_char); + appendOutputBuffer (next_char->code); +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendAttributes (FOptiAttr::char_data*& next_attr) +{ + char* attr_str; + FOptiAttr::char_data* term_attr = &term_attribute; + + // generate attribute string for the next character + attr_str = opti_attr->change_attribute (term_attr, next_attr); + + if ( attr_str ) + appendOutputBuffer (attr_str); +} + +//---------------------------------------------------------------------- +int FVTerm::appendLowerRight (FOptiAttr::char_data*& screen_char) +{ + char* SA = tcap[fc::t_enter_am_mode].string; + char* RA = tcap[fc::t_exit_am_mode].string; + + if ( ! automatic_right_margin ) + { + appendCharacter (screen_char); + } + else if ( SA && RA ) + { + appendOutputBuffer (RA); + appendCharacter (screen_char); + appendOutputBuffer (SA); + } + else + { + int x, y; + char* IC = tcap[fc::t_parm_ich].string; + char* im = tcap[fc::t_enter_insert_mode].string; + char* ei = tcap[fc::t_exit_insert_mode].string; + char* ip = tcap[fc::t_insert_padding].string; + char* ic = tcap[fc::t_insert_character].string; + + x = term->getWidth() - 2; + y = term->getHeight() - 1; + setTermXY (x, y); + appendCharacter (screen_char); + term_pos->x_ref()++; + + setTermXY (x, y); + screen_char--; + + if ( IC ) + { + appendOutputBuffer (tparm(IC, 1)); + appendCharacter (screen_char); + } + else if ( im && ei ) + { + appendOutputBuffer (im); + appendCharacter (screen_char); + + if ( ip ) + appendOutputBuffer (ip); + + appendOutputBuffer (ei); + } + else if ( ic ) + { + appendOutputBuffer (ic); + appendCharacter (screen_char); + + if ( ip ) + appendOutputBuffer (ip); + } + } + + return screen_char->code; +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendOutputBuffer (std::string& s) +{ + const char* c_string = s.c_str(); + tputs (c_string, 1, appendOutputBuffer); +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendOutputBuffer (const char* s) +{ + tputs (s, 1, appendOutputBuffer); +} + +//---------------------------------------------------------------------- +int FVTerm::appendOutputBuffer (int ch) +{ + output_buffer->push(ch); + + if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE ) + flush_out(); + + return ch; +} + +//---------------------------------------------------------------------- +void FVTerm::flush_out() +{ + while ( ! output_buffer->empty() ) + { + Fputchar (output_buffer->front()); + output_buffer->pop(); + } + + std::fflush(stdout); +} diff --git a/src/fvterm.h b/src/fvterm.h new file mode 100644 index 00000000..fab65de5 --- /dev/null +++ b/src/fvterm.h @@ -0,0 +1,252 @@ +// File: fvterm.h +// Provides: class FVTerm +// +// Inheritance diagram +// ═══════════════════ +// +// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏ +// ▕ FObject ▏ ▕ FTerm ▏ +// ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ +// ▲ ▲ +// │ │ +// └─────┬─────┘ +// │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ + + +#ifndef _FVTERM_H +#define _FVTERM_H + +#include "fterm.h" + + +// Buffer size for character output on the terminal +#define TERMINAL_OUTPUT_BUFFER_SIZE 32768 + +// class forward declaration +class FWidget; + + +//---------------------------------------------------------------------- +// class FVTerm +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FVTerm : public FObject, public FTerm +{ + private: + static std::queue* output_buffer; + static FOptiAttr::char_data term_attribute; + static FOptiAttr::char_data next_attribute; + static FPoint* term_pos; // terminal cursor position + static FPoint* cursor; // virtual print cursor + static FTermcap::tcap_map* tcap; + + static bool hidden_cursor; + static bool terminal_update_pending; + static bool force_terminal_update; + static bool terminal_updates; + static bool stop_terminal_updates; + static bool vterm_updates; + static int skipped_terminal_update; + + enum covered_state + { + non_covered, + half_covered, + fully_covered + }; + + enum character_type + { + overlapped_character, + covered_character + }; + + protected: + typedef struct + { + uInt xmin; + uInt xmax; + uInt trans_count; + } line_changes; + + typedef struct + { + int width; + int height; + int right_shadow; + int bottom_shadow; + int input_cursor_x; + int input_cursor_y; + int input_cursor_visible; + FWidget* widget; + line_changes* changes; + FOptiAttr::char_data* text; + bool visible; + } term_area; + + static term_area* vterm; // virtual terminal + static term_area* vdesktop; // virtual desktop + static term_area* last_area; // last used area + static term_area* active_area; // active area + term_area* print_area; // print area for this object + term_area* vwin; // virtual window + + protected: + void createArea (const FRect&, const FPoint&, FVTerm::term_area*&); + void createArea (int, int, int, int, FVTerm::term_area*&); + static void resizeArea (const FRect&, const FPoint&, FVTerm::term_area*); + static void resizeArea (int, int, int, int, FVTerm::term_area*); + static void removeArea (FVTerm::term_area*&); + static void restoreVTerm (const FRect&); + static void restoreVTerm (int, int, int, int); + static FVTerm::covered_state isCovered (const FPoint&, FVTerm::term_area*); + static FVTerm::covered_state isCovered (int, int, FVTerm::term_area*); + static void updateVTerm (bool); + static void updateVTerm (FVTerm::term_area*); + static bool updateVTermCursor (FVTerm::term_area*); + static bool isInsideArea (int, int, FVTerm::term_area*); + static void setAreaCursor (const FPoint&, bool, FVTerm::term_area*); + static void setAreaCursor (int, int, bool, FVTerm::term_area*); + static void getArea (const FPoint&, FVTerm::term_area*); + static void getArea (int, int, FVTerm::term_area*); + static void getArea (const FRect&, FVTerm::term_area*); + static void getArea (int, int, int, int, FVTerm::term_area*); + static void putArea (const FPoint&, FVTerm::term_area*); + static void putArea (int, int, FVTerm::term_area*); + static void scrollAreaForward (FVTerm::term_area*); + static void scrollAreaReverse (FVTerm::term_area*); + static void clearArea (FVTerm::term_area*); + static FOptiAttr::char_data getCharacter (int, const FPoint&, FVTerm*); + static FOptiAttr::char_data getCharacter (int, int, int, FVTerm*); + static FOptiAttr::char_data getCoveredCharacter (const FPoint&, FVTerm*); + static FOptiAttr::char_data getCoveredCharacter (int, int, FVTerm*); + static FOptiAttr::char_data getOverlappedCharacter (const FPoint&, FVTerm*); + static FOptiAttr::char_data getOverlappedCharacter (int, int, FVTerm*); + + private: + // Disable copy constructor + FVTerm (const FVTerm&); + // Disable assignment operator (=) + FVTerm& operator = (const FVTerm&); + + void init(); + void finish(); + term_area* getPrintArea(); + void setPrintArea (term_area*); + + // Friend class + friend class FWidget; + + public: + // Constructor + explicit FVTerm (FVTerm* = 0); + // Destructor + ~FVTerm(); + + virtual const char* getClassName() const; + + static void setTermXY (register int, register int); + + static bool hideCursor (bool); + static bool hideCursor(); + static bool showCursor(); + static bool isCursorHidden(); + + static short getTermForegroundColor(); + static short getTermBackgroundColor(); + FVTerm::term_area* getVWin() const; + void createVTerm (const FRect&); + void createVTerm (int, int); + static void resizeVTerm (const FRect&); + static void resizeVTerm (int, int); + static void putVTerm(); + static void updateTerminal (bool); + static void updateTerminal(); + static bool updateTerminalCursor(); + static void processTerminalUpdate(); + static bool isInsideTerminal (int, int); + + void setPrintCursor (const FPoint&); + void setPrintCursor (register int, register int); + FPoint* getPrintPos() const; + int printf (const wchar_t*, ...); + int printf (const char*, ...) + #if defined(__clang__) + __attribute__((__format__ (__printf__, 2, 3))) + #elif defined(__GNUC__) + __attribute__ ((format (printf, 2, 3))) + #endif + ; + int print (const std::wstring&); + int print (FVTerm::term_area*, const std::wstring&); + int print (const wchar_t*); + int print (FVTerm::term_area*, const wchar_t*); + int print (const char*); + int print (FVTerm::term_area*, const char*); + int print (const std::string&); + int print (FVTerm::term_area*, const std::string&); + int print (FString&); + int print (FVTerm::term_area*, FString&); + int print (int); + int print (FVTerm::term_area*, int); + static void newFontChanges (FOptiAttr::char_data*&); + static void charsetChanges (FOptiAttr::char_data*&); + static void appendCharacter (FOptiAttr::char_data*&); + static void appendAttributes (FOptiAttr::char_data*&); + static int appendLowerRight (FOptiAttr::char_data*&); + static void appendOutputBuffer (std::string&); + static void appendOutputBuffer (const char*); + static int appendOutputBuffer (int); + static void flush_out(); +}; + +#pragma pack(pop) + +// FVTerm inline functions +//---------------------------------------------------------------------- +inline void FVTerm::setPrintArea (term_area* area) +{ print_area = area; } + +//---------------------------------------------------------------------- +inline const char* FVTerm::getClassName() const +{ return "FVTerm"; } + +//---------------------------------------------------------------------- +inline bool FVTerm::hideCursor() +{ return hideCursor(true); } + +//---------------------------------------------------------------------- +inline bool FVTerm::showCursor() +{ return hideCursor(false); } + +//---------------------------------------------------------------------- +inline bool FVTerm::isCursorHidden() +{ return hidden_cursor; } + +//---------------------------------------------------------------------- +inline short FVTerm::getTermForegroundColor() +{ return next_attribute.fg_color; } + +//---------------------------------------------------------------------- +inline short FVTerm::getTermBackgroundColor() +{ return next_attribute.bg_color; } + +//---------------------------------------------------------------------- +inline FVTerm::term_area* FVTerm::getVWin() const +{ return vwin; } + +//---------------------------------------------------------------------- +inline void FVTerm::setPrintCursor (const FPoint& pos) +{ setPrintCursor (pos.getX(), pos.getY()); } + +//---------------------------------------------------------------------- +inline void FVTerm::setPrintCursor (register int x, register int y) +{ cursor->setPoint(x,y); } + +#endif // _FVTERM_H diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 113533de..d86f0f08 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -5,7 +5,7 @@ #include "fmenubar.h" #include "fstatusbar.h" #include "fwidget.h" -#include "fwindow.h" + // global FWidget object static FWidget* rootObject = 0; @@ -30,7 +30,7 @@ FWidget::widget_colors FWidget::wc; // constructors and destructor //---------------------------------------------------------------------- FWidget::FWidget (FWidget* parent) - : FObject(parent) + : FVTerm(parent) , callback_objects() , member_callback_objects() , accelerator_list(0) @@ -56,7 +56,6 @@ FWidget::FWidget (FWidget* parent) , wshadow(0,0) , foreground_color(fc::Default) , background_color(fc::Default) - , print_area(0) , statusbar_message() { resize_term = false; @@ -366,33 +365,6 @@ void FWidget::setColorTheme() } } -//---------------------------------------------------------------------- -FTerm::term_area* FWidget::getPrintArea() -{ - // returns the print area of this object - if ( print_area ) - return print_area; - else - { - FWidget* obj = static_cast(this); - FWidget* p_obj = static_cast(obj->getParent()); - - while ( ! obj->vwin && p_obj ) - { - obj = p_obj; - p_obj = static_cast(p_obj->getParent()); - } - - if ( obj->vwin ) - { - print_area = obj->vwin; - return print_area; - } - } - - return vdesktop; -} - // protected methods of FWidget //---------------------------------------------------------------------- @@ -1544,7 +1516,7 @@ bool FWidget::setFocus (bool on) // set window focus if ( on && window ) { - if ( ! window->isActiveWindow() ) + if ( ! window->isWindowActive() ) { bool has_raised = window->raiseWindow(); FWindow::setActiveWindow(window); @@ -1852,7 +1824,7 @@ void FWidget::getTermSize() void FWidget::setTermSize (int w, int h) { // Set xterm size to w x h - if ( xterm_terminal ) + if ( isXTerminal() ) { rootObject->wsize.setRect(1, 1, w, h); rootObject->adjust_wsize = rootObject->wsize; @@ -1945,6 +1917,23 @@ bool FWidget::setCursorPos (register int x, register int y) return false; } +//---------------------------------------------------------------------- +void FWidget::setPrintPos (register int x, register int y) +{ + setPrintCursor ( offset.getX1() + adjust_wsize.getX() - 1 + x, + offset.getY1() + adjust_wsize.getY() - 1 + y ); +} + +//---------------------------------------------------------------------- +FPoint FWidget::getPrintPos() const +{ + const FPoint* cur = FVTerm::getPrintPos(); + int cx = cur->getX(); + int cy = cur->getY(); + return FPoint ( cx - offset.getX1() - adjust_wsize.getX() + 1 + , cy - offset.getY1() - adjust_wsize.getY() + 1 ); +} + //---------------------------------------------------------------------- void FWidget::drawShadow() { @@ -1969,7 +1958,7 @@ void FWidget::drawShadow() if ( trans_shadow ) { // transparent shadow - printPos (x2+1, y1); + setPrintPos (x2+1, y1); setTransparent(); print (" "); unsetTransparent(); @@ -1979,12 +1968,12 @@ void FWidget::drawShadow() for (int i=1; i < getHeight(); i++) { - printPos (x2+1, y1+i); + setPrintPos (x2+1, y1+i); print (" "); } unsetTransShadow(); - printPos (x1, y2+1); + setPrintPos (x1, y2+1); setTransparent(); print (" "); unsetTransparent(); @@ -2004,7 +1993,7 @@ void FWidget::drawShadow() { // non-transparent shadow int block; - printPos (x2+1, y1); + setPrintPos (x2+1, y1); if ( isWindowWidget() ) { @@ -2031,11 +2020,11 @@ void FWidget::drawShadow() for (int i=1; i < getHeight(); i++) { - printPos (x2+1, y1+i); + setPrintPos (x2+1, y1+i); print (block); // █ } - printPos (x1+1, y2+1); + setPrintPos (x1+1, y2+1); if ( isWindowWidget() ) setInheritBackground(); @@ -2078,14 +2067,14 @@ void FWidget::clearShadow() { for (int i=0; i < getHeight(); i++) { - printPos (x2+1, y1+i); + setPrintPos (x2+1, y1+i); print (' '); // clear █ } } if ( y2 <= offset.getY2() ) { - printPos (x1+1, y2+1); + setPrintPos (x1+1, y2+1); for (int i=1; i <= getWidth(); i++) print (' '); // clear ▀ @@ -2115,7 +2104,7 @@ void FWidget::drawFlatBorder() for (int y=0; y < getHeight(); y++) { - printPos (x1-1, y1+y+1); + setPrintPos (x1-1, y1+y+1); if ( double_flatline_mask.left[uLong(y)] ) print (fc::NF_rev_border_line_right_and_left); // left+right line (on left side) @@ -2123,7 +2112,7 @@ void FWidget::drawFlatBorder() print (fc::NF_rev_border_line_right); // right line (on left side) } - printPos (x2, y1+1); + setPrintPos (x2, y1+1); for (int y=0; y < getHeight(); y++) { @@ -2132,10 +2121,10 @@ void FWidget::drawFlatBorder() else print (fc::NF_border_line_left); // left line (on right side) - printPos (x2, y1+y+2); + setPrintPos (x2, y1+y+2); } - printPos (x1, y1); + setPrintPos (x1, y1); for (int x=0; x < getWidth(); x++) { @@ -2145,7 +2134,7 @@ void FWidget::drawFlatBorder() print (fc::NF_border_line_bottom); // bottom line (at top) } - printPos (x1, y2); + setPrintPos (x1, y2); for (int x=0; x < getWidth(); x++) { @@ -2177,7 +2166,7 @@ void FWidget::clearFlatBorder() // clear on left side for (register int y=0; y < getHeight(); y++) { - printPos (x1-1, y1+y+1); + setPrintPos (x1-1, y1+y+1); if ( double_flatline_mask.left[uLong(y)] ) print (fc::NF_border_line_left); @@ -2188,7 +2177,7 @@ void FWidget::clearFlatBorder() // clear on right side for (register int y=0; y < getHeight(); y++) { - printPos (x2, y1+y+1); + setPrintPos (x2, y1+y+1); if ( double_flatline_mask.right[uLong(y)] ) print (fc::NF_rev_border_line_right); @@ -2197,7 +2186,7 @@ void FWidget::clearFlatBorder() } // clear at top - printPos (x1, y1); + setPrintPos (x1, y1); for (register int x=0; x < getWidth(); x++) { @@ -2208,7 +2197,7 @@ void FWidget::clearFlatBorder() } // clear at bottom - printPos (x1, y2); + setPrintPos (x1, y2); for (register int x=0; x < getWidth(); x++) { @@ -2357,7 +2346,7 @@ void FWidget::drawBorder (int x1, int y1, int x2, int y2) if ( isNewFont() ) { - printPos (x1, y1); + setPrintPos (x1, y1); print (fc::NF_border_corner_middle_upper_left); // ┌ for (int x=x1+1; x < x2; x++) @@ -2367,13 +2356,13 @@ void FWidget::drawBorder (int x1, int y1, int x2, int y2) for (int y=y1+1; y <= y2; y++) { - printPos (x1, y); + setPrintPos (x1, y); print (fc::NF_border_line_left); // border left ⎸ - printPos (x2, y); + setPrintPos (x2, y); print (fc::NF_rev_border_line_right); // border right⎹ } - printPos (x1, y2); + setPrintPos (x1, y2); print (fc::NF_border_corner_middle_lower_left); // └ for (int x=x1+1; x < x2; x++) @@ -2383,7 +2372,7 @@ void FWidget::drawBorder (int x1, int y1, int x2, int y2) } else { - printPos (x1, y1); + setPrintPos (x1, y1); print (fc::BoxDrawingsDownAndRight); // ┌ for (int x=x1+1; x < x2; x++) @@ -2393,13 +2382,13 @@ void FWidget::drawBorder (int x1, int y1, int x2, int y2) for (int y=y1+1; y < y2; y++) { - printPos (x1, y); + setPrintPos (x1, y); print (fc::BoxDrawingsVertical); // │ - printPos (x2, y); + setPrintPos (x2, y); print (fc::BoxDrawingsVertical); // │ } - printPos (x1, y2); + setPrintPos (x1, y2); print (fc::BoxDrawingsUpAndRight); // └ for (int x=x1+1; x < x2; x++) @@ -2409,9 +2398,9 @@ void FWidget::drawBorder (int x1, int y1, int x2, int y2) for (int x=x1+1; x < x2; x++) { - printPos (x, y1); + setPrintPos (x, y1); print (fc::BoxDrawingsHorizontal); // ─ - printPos (x, y2); + setPrintPos (x, y2); print (fc::BoxDrawingsHorizontal); // ─ } } diff --git a/src/fwidget.h b/src/fwidget.h index 694d850a..82519cbb 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ 1 1▕▔▔▔▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏-┬- - - -▕ FStatusBar ▏ // ▕▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▁▁▁▏ @@ -66,7 +71,7 @@ #ifndef _FWIDGET_H #define _FWIDGET_H -#include "fterm.h" +#include "fvterm.h" // Callback macros @@ -88,7 +93,7 @@ class FMenuBar; #pragma pack(push) #pragma pack(1) -class FWidget : public FObject, public FTerm +class FWidget : public FVTerm { public: typedef std::vector widgetList; @@ -302,7 +307,6 @@ class FWidget : public FObject, public FTerm short foreground_color; short background_color; - term_area* print_area; FString statusbar_message; static FStatusBar* statusbar; @@ -310,7 +314,6 @@ class FWidget : public FObject, public FTerm static FWidget* show_root_widget; static FWidget* redraw_root_widget; - friend class FTerm; friend class FApplication; friend class FToggleButton; @@ -325,8 +328,6 @@ class FWidget : public FObject, public FTerm void processDestroy(); virtual void draw(); static void setColorTheme(); - term_area* getPrintArea(); - void setPrintArea (term_area*); protected: virtual void adjustSize(); @@ -504,8 +505,8 @@ class FWidget : public FObject, public FTerm bool setCursorPos (register int, register int); void unsetCursorPos(); - void printPos (const FPoint&); - void printPos (register int, register int); + void setPrintPos (const FPoint&); + void setPrintPos (register int, register int); FPoint getPrintPos() const; static void setNormal(); @@ -612,10 +613,6 @@ class FWidget : public FObject, public FTerm inline void FWidget::processDestroy() { emitCallback("destroy"); } -//---------------------------------------------------------------------- -inline void FWidget::setPrintArea (term_area* area) -{ print_area = area; } - //---------------------------------------------------------------------- inline const char* FWidget::getClassName() const { return "FWidget"; } @@ -928,24 +925,8 @@ inline void FWidget::unsetCursorPos() { widget_cursor_position.setPoint(-1,-1); } //---------------------------------------------------------------------- -inline void FWidget::printPos (const FPoint& pos) -{ printPos (pos.getX(), pos.getY()); } - -//---------------------------------------------------------------------- -inline void FWidget::printPos (register int x, register int y) -{ - cursor->setPoint ( offset.getX1() + adjust_wsize.getX() - 1 + x, - 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::setPrintPos (const FPoint& pos) +{ setPrintPos (pos.getX(), pos.getY()); } //---------------------------------------------------------------------- inline void FWidget::setNormal() diff --git a/src/fwindow.cpp b/src/fwindow.cpp index a9248910..508b4e47 100644 --- a/src/fwindow.cpp +++ b/src/fwindow.cpp @@ -9,11 +9,12 @@ // static attributes FWindow* FWindow::previous_widget = 0; + //---------------------------------------------------------------------- // class FWindow //---------------------------------------------------------------------- -// constructors and destructor +// constructor and destructor //---------------------------------------------------------------------- FWindow::FWindow(FWidget* parent) : FWidget(parent) @@ -161,7 +162,7 @@ void FWindow::drawBorder() int y1 = 1; int y2 = 1 + getHeight() - 1; - printPos (x1, y1); + setPrintPos (x1, y1); print (fc::NF_border_corner_upper_left); // ⎡ for (int x=x1+1; x < x2; x++) @@ -171,22 +172,22 @@ void FWindow::drawBorder() for (int y=y1+1; y < y2; y++) { - printPos (x1, y); + setPrintPos (x1, y); // border left ⎸ print (fc::NF_border_line_left); - printPos (x2, y); + setPrintPos (x2, y); // border right⎹ print (fc::NF_rev_border_line_right); } - printPos (x1, y2); + setPrintPos (x1, y2); // lower left corner border ⎣ print (fc::NF_border_corner_lower_left); for (int x=2; x < getWidth(); x++) // low line _ print (fc::NF_border_line_bottom); - printPos (x2, y2); + setPrintPos (x2, y2); // lower right corner border ⎦ print (fc::NF_rev_border_corner_lower_right); } @@ -283,7 +284,7 @@ FWindow* FWindow::getWindowWidgetAt (int x, int y) { FWindow* w = static_cast(*iter); - if ( ! w->isHiddenWindow() + if ( ! w->isWindowHidden() && w->getTermGeometry().contains(x,y) ) return w; } @@ -571,7 +572,7 @@ void FWindow::setActiveWindow (FWindow* window) { if ( *iter == window ) { - if ( ! window->isActiveWindow() ) + if ( ! window->isWindowActive() ) { window->activateWindow(); FEvent ev(fc::WindowActive_Event); @@ -582,7 +583,7 @@ void FWindow::setActiveWindow (FWindow* window) { FWindow* w = static_cast(*iter); - if ( w->isActiveWindow() ) + if ( w->isWindowActive() ) { w->deactivateWindow(); FEvent ev(fc::WindowInactive_Event); @@ -631,7 +632,7 @@ void FWindow::switchToPrevWindow() if ( w && w != active_window - && ! (w->isHiddenWindow() || w->isActiveWindow()) + && ! (w->isWindowHidden() || w->isWindowActive()) && w != static_cast(statusBar()) && w != static_cast(menuBar()) ) { @@ -647,7 +648,7 @@ void FWindow::switchToPrevWindow() { FWidget* focus_widget = active_window->getWindowFocusWidget(); - if ( ! active_window->isActiveWindow() ) + if ( ! active_window->isWindowActive() ) setActiveWindow(active_window); if ( focus_widget ) @@ -668,10 +669,10 @@ bool FWindow::activatePrevWindow() if ( w ) { - if ( w->isActiveWindow() ) + if ( w->isWindowActive() ) return true; - if ( w && ! w->isHiddenWindow() ) + if ( w && ! w->isWindowHidden() ) { setActiveWindow(w); return true; @@ -695,7 +696,7 @@ bool FWindow::activateWindow (bool on) } //---------------------------------------------------------------------- -bool FWindow::isHiddenWindow() const +bool FWindow::isWindowHidden() const { // returns the window hidden state term_area* area = getVWin(); diff --git a/src/fwindow.h b/src/fwindow.h index 895e23df..dd7e9972 100644 --- a/src/fwindow.h +++ b/src/fwindow.h @@ -11,6 +11,11 @@ // │ │ // └─────┬─────┘ // │ +// ▕▔▔▔▔▔▔▔▔▏ +// ▕ FVTerm ▏ +// ▕▁▁▁▁▁▁▁▁▏ +// ▲ +// │ // ▕▔▔▔▔▔▔▔▔▔▏ // ▕ FWidget ▏ // ▕▁▁▁▁▁▁▁▁▁▏ @@ -114,10 +119,10 @@ class FWindow : public FWidget bool activateWindow (bool); bool activateWindow(); bool deactivateWindow(); - bool isActiveWindow() const; - bool isHiddenWindow() const; - bool setResizeable (bool); - bool setResizeable(); + bool isWindowActive() const; + bool isWindowHidden() const; + virtual bool setResizeable (bool); + virtual bool setResizeable(); bool unsetResizeable(); bool isResizeable(); bool setTransparentShadow (bool); @@ -175,7 +180,7 @@ inline bool FWindow::deactivateWindow() { return activateWindow(false); } //---------------------------------------------------------------------- -inline bool FWindow::isActiveWindow() const +inline bool FWindow::isWindowActive() const { return window_active; } //---------------------------------------------------------------------- diff --git a/test/calculator.cpp b/test/calculator.cpp index d6271bcb..b273c62c 100644 --- a/test/calculator.cpp +++ b/test/calculator.cpp @@ -327,7 +327,7 @@ void Calc::drawDispay() if ( isMonochron() ) setReverse(false); - printPos (3,3); + setPrintPos (3,3); print(display); print(L' '); setColor(wc.dialog_fg, wc.dialog_bg); @@ -338,15 +338,15 @@ void Calc::drawDispay() if ( isNewFont() ) { FString bottom_line(33, wchar_t(fc::NF_border_line_bottom)); - printPos (3,2); + setPrintPos (3,2); print (bottom_line); - printPos (2,3); + setPrintPos (2,3); print (wchar_t(fc::NF_rev_border_line_right)); - printPos (36,3); + setPrintPos (36,3); print (wchar_t(fc::NF_border_line_left)); FString top_bottom_line_5(5, wchar_t(fc::NF_border_line_up_and_down)); FString top_line_2(2, wchar_t(fc::NF_border_line_upper)); - printPos (3,4); + setPrintPos (3,4); print ( top_bottom_line_5 + top_line_2 + top_bottom_line_5 + top_line_2 + top_bottom_line_5 + top_line_2 @@ -358,7 +358,7 @@ void Calc::drawDispay() FString separator = FString(wchar_t(fc::BoxDrawingsVerticalAndRight)) + FString(35, wchar_t(fc::BoxDrawingsHorizontal)) + FString(wchar_t(fc::BoxDrawingsVerticalAndLeft)); - printPos (1,4); + setPrintPos (1,4); print(separator); } diff --git a/test/keyboard.cpp b/test/keyboard.cpp index b3bf114d..8df9b658 100644 --- a/test/keyboard.cpp +++ b/test/keyboard.cpp @@ -66,7 +66,7 @@ void keyboard::draw() setNormal(); setColor(fc::Default, fc::Default); clearArea (vdesktop); - printPosTerm (1,1); + setPrintPos (1,1); print ("---------------\n"); print ("Press Q to quit\n"); print ("---------------\n"); diff --git a/test/mandelbrot.cpp b/test/mandelbrot.cpp index dae22246..eb339d4a 100644 --- a/test/mandelbrot.cpp +++ b/test/mandelbrot.cpp @@ -68,7 +68,7 @@ void Mandelbrot::draw() for (y0=y_min; y0 < y_max && current_line < Lines; y0+=dY) { current_line++; - printPos (xoffset, yoffset + current_line); + setPrintPos (xoffset, yoffset + current_line); for (x0=x_min; x0 < x_max; x0+=dX) { diff --git a/test/term-attributes.cpp b/test/term-attributes.cpp index 6e5dfa1b..2ddd8560 100644 --- a/test/term-attributes.cpp +++ b/test/term-attributes.cpp @@ -231,7 +231,7 @@ void AttribDemo::printAltCharset() if ( ! isMonochron() ) setColor (wc.label_fg, wc.label_bg); - printPos (1,1); + setPrintPos (1,1); print("alternate charset: "); if ( parent->bgcolor == fc::Default ) @@ -262,7 +262,7 @@ void AttribDemo::draw() for (int y=0; y < getParentWidget()->getHeight()-7; y++) { - printPos (1, 2+y); + setPrintPos (1, 2+y); if ( ! isMonochron() ) setColor (wc.label_fg, wc.label_bg); @@ -366,7 +366,7 @@ void AttribDemo::draw() if ( ! isMonochron() ) setColor(wc.label_fg, wc.label_bg); - printPos (1, 15); + setPrintPos (1, 15); short bg = static_cast(getParent())->bgcolor; print (" Background color:"); @@ -375,7 +375,7 @@ void AttribDemo::draw() else printf ( " %d", bg); - printPos (16, 17); + setPrintPos (16, 17); print ("Change background color ->"); updateVTerm(true); } diff --git a/test/timer.cpp b/test/timer.cpp index be7559ce..b74f2706 100644 --- a/test/timer.cpp +++ b/test/timer.cpp @@ -72,7 +72,7 @@ void timer::draw() setNormal(); setColor (fc::Default, fc::Default); clearArea (vdesktop); - printPosTerm (1,1); + setPrintPos (1,1); print ("---------------\n"); print ("Press Q to quit\n"); print ("---------------\n"); diff --git a/test/transparent.cpp b/test/transparent.cpp index c2f72af3..980015b7 100644 --- a/test/transparent.cpp +++ b/test/transparent.cpp @@ -85,7 +85,7 @@ void Transparent::draw() for (int n=1; n <= getClientHeight(); n++) { - printPos (2, 2+n); + setPrintPos (2, 2+n); print(line); } @@ -217,9 +217,9 @@ void MainWindow::draw() setReverse(true); setColor(); - printPos (2,4); + setPrintPos (2,4); print(line1); - printPos (2,5); + setPrintPos (2,5); print(line2); if ( isMonochron() ) diff --git a/test/windows.cpp b/test/windows.cpp index 63232972..80902931 100644 --- a/test/windows.cpp +++ b/test/windows.cpp @@ -339,7 +339,7 @@ Window::~Window() //---------------------------------------------------------------------- void Window::activateWindow (FDialog* win) { - if ( win && ! win->isHiddenWindow() && ! win->isActiveWindow() ) + if ( win && ! win->isWindowHidden() && ! win->isWindowActive() ) { bool has_raised = FWindow::raiseWindow(win); win->activateDialog(); @@ -443,7 +443,7 @@ void Window::cb_next (FWidget*, void*) while ( iter != dialog_list->end() ) { - if ( static_cast(*iter)->isActiveWindow() ) + if ( static_cast(*iter)->isWindowActive() ) { FDialog* next; widgetList::const_iterator next_element; @@ -484,7 +484,7 @@ void Window::cb_previous (FWidget*, void*) --iter; if ( (*iter)->isDialogWidget() - && static_cast(*iter)->isActiveWindow() ) + && static_cast(*iter)->isWindowActive() ) { FDialog* prev; widgetList::const_iterator prev_element;