From fa05774a13d1a63a3f5c1e52d95f1263da34c6f2 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Wed, 30 Sep 2015 22:39:02 +0200 Subject: [PATCH] Some code improvements --- .travis.yml | 6 +- ChangeLog | 3 + README.md | 3 +- build.sh | 2 +- doc/class-diagram.txt | 33 ++++--- src/fbutton.cpp | 13 ++- src/ffiledialog.cpp | 10 +-- src/flabel.cpp | 21 +++-- src/fmenu.cpp | 166 ++++++++++++++++++++--------------- src/fmenu.h | 17 +++- src/fmenubar.cpp | 154 ++++++++++++++++++++++----------- src/fmenubar.h | 4 +- src/fmenuitem.cpp | 115 +++++++++++++++++-------- src/fmenuitem.h | 6 +- src/foptimove.cpp | 7 +- src/fstring.cpp | 80 ++++++++++------- src/fterm.cpp | 172 ++++++++++++++++++++----------------- test/string-operations.cpp | 16 +++- 18 files changed, 514 insertions(+), 314 deletions(-) diff --git a/.travis.yml b/.travis.yml index beb01972..41949436 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,15 @@ install: - lsb_release -a - uname -a - sudo apt-get update - - sudo apt-get -y install libglib2.0-dev libncursesw5-dev libgpm-dev autoconf-archive + - sudo apt-get -y install autotools-dev automake autoconf autoconf-archive libtool libglib2.0-dev libncurses5-dev libgpm-dev gperf - git clone git://github.com/gansm/finalcut.git - cd finalcut - autoreconf -v --install --force - ./configure --prefix=/usr - - make + - make V=1 -j10 - sudo make install - cd .. - rm -rf finalcut script: - - autoreconf -v --install --force && ./configure --prefix=/usr && make && make check + - autoreconf -v --install --force && ./configure --prefix=/usr && make -j10 && make check diff --git a/ChangeLog b/ChangeLog index 36bb1f19..64890b2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2015-09-39 Markus Gans + * Some code improvements + 2015-09-27 Markus Gans * Add methods getPos and setPos to FRect and FWidget diff --git a/README.md b/README.md index 1ea118d0..b1de4ccb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -The Final Cut [![Build Status](https://travis-ci.org/gansm/finalcut.svg?branch=master)](https://travis-ci.org/gansm/finalcut) +The Final Cut [![Build Status](https://travis-ci.org/gansm/finalcut.svg?branch=master)](https://travis-ci.org/gansm/finalcut) [![Coverity Scan Status](https://scan.coverity.com/projects/6508/badge.svg)](https://scan.coverity.com/projects/6508) + ============= The Final Cut is a class library and widget toolkit with full mouse support for creating a text-based user interface. The library supports the programmer to develop an application for the text console. It allows the simultaneous handling of multiple windows on the screen. The C++ class design was inspired by the Qt framework. It provides common controls like dialog windows, push buttons, check boxes, radio buttons, input lines, list boxes, status bars and so on. diff --git a/build.sh b/build.sh index 3a42f50a..ea91abd5 100755 --- a/build.sh +++ b/build.sh @@ -24,5 +24,5 @@ case "$1" in ;; esac -make +make V=1 -j10 # make install diff --git a/doc/class-diagram.txt b/doc/class-diagram.txt index 763d945b..10cd4a25 100644 --- a/doc/class-diagram.txt +++ b/doc/class-diagram.txt @@ -37,7 +37,7 @@ : ┌────┤ FApplication │ : │ └──────────────┘ : │ ┌─────────┐1 - : ├────┤ FButton ├-----------------------------. + : ├────┤ FButton ├-----------------------------┐ : │ └─────────┘ : : │ ┌────────┐1 : : ├────┤ FLabel ├------------------------------: @@ -52,11 +52,11 @@ └─────────┘ │└───┬─┬───┘ ├────┤ FToggleButton │◄─┼──┤ FCheckBox ├-----: │ :1:1 │ └───────────────┘ │ └───────────┘ : ┌───────┐ │ : : │ ┌──────────────┐ │ ┌─────────┐1 : - │ FTerm │◄─┘ : : ├────┤ FProgressbar │ └──┤ FSwitch ├-------: *┌─────────┐ - └──┬─┬──┘ : : │ └──────────────┘ └─────────┘ :---┤ FString │ - :1:1 : : │ ┌────────────┐ : └─────────┘ - : └----------: : ├────┤ FScrollbar │ : - :1 : : │ └────────────┘ : + │ FTerm │◄─┘ : : ├────┤ FProgressbar │ └──┤ FSwitch ├-------: + └──┬─┬──┘ : : │ └──────────────┘ └─────────┘ : + :1:1 : : │ ┌────────────┐ : *┌─────────┐ + : └----------: : ├────┤ FScrollbar │ ├---┤ FString │ + :1 : : │ └────────────┘ : └─────────┘ ┌────┴──────┐ : : │ ┌───────────┐1 : │ FOptiMove │ : : ├────┤ FTextView ├---------------------------: └───────────┘ : : │ └───────────┘ : @@ -70,16 +70,23 @@ : : │ ┌─────────────┐1 : : : ┌───┴─────┐ ┌─────────┐ ┌──┤ FFileDialog ├----: : : │ FWindow │◄─┤ FDialog │◄──┤ └─────────────┘ : - : : └─────────┘ └────┬────┘ │ ┌─────────────┐1 : - : : : └──┤ FMessageBox ├----: - : : : └─────────────┘ : - : : 1└------------------------------: - : : : - : └---------------------------------------------------' + : : └───┬─────┘ └────┬────┘ │ ┌─────────────┐1 : + : : ▲ 1: └──┤ FMessageBox ├----: + : : │ : └─────────────┘ : + : : │ └------------------------------: + : : └───────────────────┐ ┌──────────┐ : + : : │ ┌───┤ FMenuBar │ : + : : ├───┤ └──────────┘ : + : : ┌───────────┐ │ │ ┌───────┐ : + : : │ FMenuList │◄───┘ └───┤ FMenu │ : + : : └─────┬─────┘ └───────┘ : + : : : ┌───────────┐ : + : : └------------------┤ FMenuItem │ : + : : └───────────┘ : + : └---------------------------------------------------┘ : *┌────────┐ :---┤ FPoint │ : └────────┘ : *┌───────┐ └---┤ FRect │ └───────┘ - diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 520753dd..62dae312 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -81,8 +81,17 @@ uChar FButton::getHotkey() length = int(text.getLength()); for (int i=0; i < length; i++) - if ( (i+1 < length) && (text[uInt(i)] == '&') ) - return uChar(text[uInt(++i)]); + { + try + { + if ( (i+1 < length) && (text[uInt(i)] == '&') ) + return uChar(text[uInt(++i)]); + } + catch (const std::out_of_range&) + { + return 0;; + } + } return 0; } diff --git a/src/ffiledialog.cpp b/src/ffiledialog.cpp index afe31be8..2b2fc0a6 100644 --- a/src/ffiledialog.cpp +++ b/src/ffiledialog.cpp @@ -214,7 +214,7 @@ void FFileDialog::draw() inline bool FFileDialog::pattern_match ( const char* pattern , const char* fname ) { - char search[128]; + char search[128] = {}; if ( show_hidden && fname[0] == '.' && fname[1] != '\0' ) // hidden files { search[0] = '.'; @@ -222,7 +222,7 @@ inline bool FFileDialog::pattern_match ( const char* pattern strncat(search, pattern, sizeof(search) - strlen(search) - 1); } else - strncpy(search, pattern, sizeof(search)); + strncpy(search, pattern, sizeof(search) - 1); if ( fnmatch (search, fname, FNM_PERIOD) == 0 ) return true; @@ -610,9 +610,9 @@ int FFileDialog::readDir() if ( next->d_type == DT_LNK ) // symbolic link { - char resolved_path[MAXPATHLEN]; - char symLink[MAXPATHLEN]; - strncpy(symLink, dir, sizeof(symLink)); + char resolved_path[MAXPATHLEN] = {}; + char symLink[MAXPATHLEN] = {}; + strncpy(symLink, dir, sizeof(symLink) - 1); strncat(symLink, next->d_name, sizeof(symLink) - strlen(symLink) - 1); if ( realpath(symLink, resolved_path) != 0 ) // follow link diff --git a/src/flabel.cpp b/src/flabel.cpp index 07494a87..51d3892f 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -75,8 +75,17 @@ uChar FLabel::getHotkey() length = text.getLength(); for (uInt i=0; i < length; i++) - if ( (i+1 < length) && (text[i] == '&') ) - return uChar(text[++i]); + { + try + { + if ( (i+1 < length) && (text[i] == '&') ) + return uChar(text[++i]); + } + catch (const std::out_of_range&) + { + return 0;; + } + } return 0; } @@ -240,15 +249,13 @@ void FLabel::draw() { length = multiline_text[y].getLength(); LabelText = new wchar_t[length+1]; + src = const_cast(multiline_text[y].wc_str()); + dest = const_cast(LabelText); if ( ! hotkey_printed ) - { - src = const_cast(multiline_text[y].wc_str()); - dest = const_cast(LabelText); hotkeypos = getHotkeyPos(src, dest, length); - } else - LabelText = const_cast(multiline_text[y].wc_str()); + wcsncpy(dest, src, length); gotoxy (xpos+xmin-1, ypos+ymin-1+int(y)); diff --git a/src/fmenu.cpp b/src/fmenu.cpp index 8cc10907..1a8504b8 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -12,9 +12,9 @@ FMenu::FMenu(FWidget* parent) : FWindow(parent) , item(0) + , selectedListItem(0) , super_menu(0) , maxItemWidth(0) - , current(0) , mouse_down(false) { init(); @@ -24,9 +24,9 @@ FMenu::FMenu(FWidget* parent) FMenu::FMenu (FString& txt, FWidget* parent) : FWindow(parent) , item(0) + , selectedListItem(0) , super_menu(0) , maxItemWidth(0) - , current(0) , mouse_down(false) { item = new FMenuItem(txt, parent); @@ -37,9 +37,9 @@ FMenu::FMenu (FString& txt, FWidget* parent) FMenu::FMenu (const std::string& txt, FWidget* parent) : FWindow(parent) , item(0) + , selectedListItem(0) , super_menu(0) , maxItemWidth(0) - , current(0) , mouse_down(false) { item = new FMenuItem(txt, parent); @@ -50,9 +50,9 @@ FMenu::FMenu (const std::string& txt, FWidget* parent) FMenu::FMenu (const char* txt, FWidget* parent) : FWindow(parent) , item(0) + , selectedListItem(0) , super_menu(0) , maxItemWidth(0) - , current(0) , mouse_down(false) { item = new FMenuItem(txt, parent); @@ -101,17 +101,11 @@ void FMenu::init() setGeometry (1, 1 , 10, 2, false); // initialize geometry values window_object = true; addWindow(this); + hide(); foregroundColor = wc.menu_active_fg; backgroundColor = wc.menu_active_bg; - FWidget* old_focus = FWidget::getFocusWidget(); - if ( old_focus ) - { - setFocus(); - old_focus->redraw(); - } - item->setMenu(this); } @@ -195,25 +189,12 @@ int FMenu::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) //---------------------------------------------------------------------- void FMenu::draw() { - if ( itemlist.empty() ) - return; - - if ( current < 1 ) - { - current = 1; - itemlist[0]->setSelected(); - } - - menu_dimension(); - // fill the background - setColor (foregroundColor, backgroundColor); + setColor (wc.menu_active_fg, wc.menu_active_bg); setUpdateVTerm(false); clrscr(); drawBorder(); - drawItems(); - setUpdateVTerm(true); } @@ -393,6 +374,7 @@ void FMenu::onMouseDown (FMouseEvent* ev) while ( iter != end ) { (*iter)->unsetSelected(); + selectedListItem = 0; ++iter; } } @@ -406,32 +388,36 @@ void FMenu::onMouseDown (FMouseEvent* ev) if ( ! itemlist.empty() ) { std::vector::const_iterator iter, end; - int X = 1; + bool focus_changed = false; iter = itemlist.begin(); end = itemlist.end(); while ( iter != end ) { - int x1, x2, mouse_x, mouse_y, txt_length; + int x1, x2, y, mouse_x, mouse_y; - x1 = X; - txt_length = int((*iter)->getText().getLength()); - x2 = x1 + txt_length + 1; + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + y = (*iter)->getY(); mouse_x = ev->getX(); mouse_y = ev->getY(); if ( mouse_x >= x1 && mouse_x <= x2 - && mouse_y == 1 + && mouse_y == y && ! (*iter)->isSelected() ) { + if ( hasSelectedListItem() ) + unselectItemInList(); (*iter)->setSelected(); - redraw(); + selectedListItem = *iter; + focus_changed = true; } - X = x2 + 2; ++iter; } + if ( focus_changed ) + redraw(); } } @@ -447,28 +433,36 @@ void FMenu::onMouseUp (FMouseEvent* ev) if ( ! itemlist.empty() ) { std::vector::const_iterator iter, end; - int X = 1; + bool focus_changed = false; iter = itemlist.begin(); end = itemlist.end(); while ( iter != end ) { - int x1 = X; - int txt_length = int((*iter)->getText().getLength()); - int x2 = x1 + txt_length + 1; + int x1, x2, y; + + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + y = (*iter)->getY(); if ( (*iter)->isSelected() ) { int mouse_x = ev->getX(); int mouse_y = ev->getY(); - if ( mouse_x < x1 || mouse_x > x2 || mouse_y != 1 ) - (*iter)->unsetSelected(); - redraw(); + + if ( mouse_x >= x1 + && mouse_x <= x2 + && mouse_y == y ) + { + (*iter)->processClicked(); + redraw(); + } } - X = x2 + 2; ++iter; } + if ( focus_changed ) + redraw(); } } } @@ -483,38 +477,31 @@ void FMenu::onMouseMove (FMouseEvent* ev) { std::vector::const_iterator iter, end; bool focus_changed = false; - int X=1; iter = itemlist.begin(); end = itemlist.end(); while ( iter != end ) { - int x1 = X; - int txt_length = int((*iter)->getText().getLength()); - int x2 = x1 + txt_length + 1; + int x1, x2, y, mouse_x, mouse_y; + + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + y = (*iter)->getY(); + mouse_x = ev->getX(); + mouse_y = ev->getY(); - int mouse_x = ev->getX(); - int mouse_y = ev->getY(); if ( mouse_x >= x1 && mouse_x <= x2 - && mouse_y == 1 ) + && mouse_y == y + && ! (*iter)->isSelected() ) { - if ( ! (*iter)->isSelected() ) - { - (*iter)->setSelected(); - focus_changed = true; - } + if ( hasSelectedListItem() ) + unselectItemInList(); + (*iter)->setSelected(); + selectedListItem = *iter; + focus_changed = true; } - else - { - if ( (*iter)->isSelected() ) - { - (*iter)->unsetSelected(); - focus_changed = true; - } - } - X = x2 + 2; ++iter; } if ( focus_changed ) @@ -522,9 +509,31 @@ void FMenu::onMouseMove (FMouseEvent* ev) } } +//---------------------------------------------------------------------- +void FMenu::show() +{ + if ( ! isVisible() ) + return; + + FWindow::show(); + + // set the cursor to the focus widget + if ( FWidget::getFocusWidget() + && FWidget::getFocusWidget()->isVisible() + && FWidget::getFocusWidget()->hasVisibleCursor() + && FWidget::getFocusWidget()->isCursorInside() ) + { + FWidget::getFocusWidget()->setCursor(); + showCursor(); + flush_out(); + } +} + //---------------------------------------------------------------------- void FMenu::hide() -{ } +{ + FWindow::hide(); +} //---------------------------------------------------------------------- void FMenu::setGeometry (int xx, int yy, int ww, int hh, bool adjust) @@ -537,15 +546,25 @@ void FMenu::setGeometry (int xx, int yy, int ww, int hh, bool adjust) } //---------------------------------------------------------------------- -void FMenu::insert (FMenuItem* i) +void FMenu::selectFirstItemInList() { - FMenuList::insert(i); + if ( itemlist.empty() ) + return; + + if ( ! hasSelectedListItem() ) + { + // select the first item + itemlist[0]->setSelected(); + selectedListItem = itemlist[0]; + } } //---------------------------------------------------------------------- -void FMenu::remove (FMenuItem* i) +void FMenu::unselectItemInList() { - FMenuList::remove(i); + if ( hasSelectedListItem() ) + selectedListItem->unsetSelected(); + selectedListItem = 0; } //---------------------------------------------------------------------- @@ -555,6 +574,17 @@ void FMenu::cb_menuitem_activated (FWidget* widget, void*) if ( menuitem->hasMenu() ) { - beep(); + //beep(); + } +} + +//---------------------------------------------------------------------- +void FMenu::cb_menuitem_deactivated (FWidget* widget, void*) +{ + FMenuItem* menuitem = static_cast(widget); + + if ( menuitem->hasMenu() ) + { + //beep(); } } diff --git a/src/fmenu.h b/src/fmenu.h index 4ef0a566..5bb62d15 100644 --- a/src/fmenu.h +++ b/src/fmenu.h @@ -46,9 +46,9 @@ class FMenu : public FWindow, public FMenuList { private: FMenuItem* item; + FMenuItem* selectedListItem; FMenuList* super_menu; uInt maxItemWidth; - int current; bool mouse_down; private: @@ -57,7 +57,6 @@ class FMenu : public FWindow, public FMenuList void init(); void menu_dimension(); bool isMenuBar (FWidget*) const; - FMenuList* superMenu() const; void setSuperMenu (FMenuList*); int getHotkeyPos (wchar_t*&, wchar_t*&, uInt); @@ -77,6 +76,7 @@ class FMenu : public FWindow, public FMenuList void onMouseDown (FMouseEvent*); void onMouseUp (FMouseEvent*); void onMouseMove (FMouseEvent*); + void show(); void hide(); // make every setGeometry from FWidget available using FWidget::setGeometry; @@ -91,15 +91,20 @@ class FMenu : public FWindow, public FMenuList void setSelected(); void unsetSelected(); bool isSelected() const; + void selectFirstItemInList(); + void unselectItemInList(); + bool hasSelectedListItem() const; bool hasHotkey() const; void setMenu (FMenu*); bool hasMenu() const; void setText (FString&); void setText (const std::string&); void setText (const char*); - void insert (FMenuItem*); - void remove (FMenuItem*); void cb_menuitem_activated (FWidget*, void*); + void cb_menuitem_deactivated (FWidget*, void*); + + private: + friend class FMenuItem; }; #pragma pack(pop) @@ -145,6 +150,10 @@ inline void FMenu::unsetSelected() inline bool FMenu::isSelected() const { return item->isSelected(); } +//---------------------------------------------------------------------- +inline bool FMenu::hasSelectedListItem() const +{ return selectedListItem; } + //---------------------------------------------------------------------- inline bool FMenu::hasHotkey() const { return item->hasHotkey(); } diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index ccf2a201..3c593a56 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -2,7 +2,7 @@ // Provides: class FMenuBar #include "fmenubar.h" -#include "fmessagebox.h" + //---------------------------------------------------------------------- // class FMenuBar //---------------------------------------------------------------------- @@ -12,7 +12,6 @@ FMenuBar::FMenuBar(FWidget* parent) : FWindow(parent) , mouse_down(false) - , x(-1) { init(); } @@ -113,22 +112,16 @@ void FMenuBar::draw() xmin = ymin = 1; height = 1; xpos = 1; - - menu_dimension(); - drawItems(); } //---------------------------------------------------------------------- void FMenuBar::drawItems() { - bool is_Active; - bool is_Selected; - bool is_NoUnderline; std::vector::const_iterator iter, end; int screenWidth; - x = 1; + int x = 1; screenWidth = getColumnNumber(); width = screenWidth; ypos = 1; @@ -150,7 +143,7 @@ void FMenuBar::drawItems() FString txt; uInt txt_length; int hotkeypos, to_char; - + bool is_Active, is_Selected, is_NoUnderline; is_Active = (*iter)->isActivated(); is_Selected = (*iter)->isSelected(); @@ -229,7 +222,8 @@ void FMenuBar::drawItems() x++; print (vmenubar, ' '); } - + + setColor (wc.menu_active_fg, wc.menu_active_bg); if ( is_Active && is_Selected ) setReverse(false); delete[] item_text; @@ -282,38 +276,52 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) if ( ! itemlist.empty() ) { std::vector::const_iterator iter, end; - int X = 1; + bool focus_changed = false; iter = itemlist.begin(); end = itemlist.end(); -//FMessageBox::info (this, "Info", FString().sprintf("local(%d,%d) global(%d,%d)", ev->getX(),ev->getY(),ev->getGlobalX(), ev->getGlobalY())); // + #include +//FMessageBox::info (this, "Info", FString().sprintf("local(%d,%d) global(%d,%d)", ev->getX(),ev->getY(),ev->getGlobalX(), ev->getGlobalY())); +// #include "fmessagebox.h" while ( iter != end ) { - int x1, x2, mouse_x, mouse_y, txt_length; + int x1, x2, mouse_x, mouse_y; - x1 = X; - txt_length = int((*iter)->getTextLength()); - - x2 = x1 + txt_length + 1; - mouse_x = ev->getGlobalX(); - mouse_y = ev->getGlobalY(); + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + mouse_x = ev->getX(); + mouse_y = ev->getY(); if ( mouse_x >= x1 && mouse_x <= x2 - && mouse_y == 1 - && ! (*iter)->isSelected() ) + && mouse_y == 1 ) { - (*iter)->setSelected(); - redraw(); + if ( ! (*iter)->isSelected() ) + { + (*iter)->setSelected(); + focus_changed = true; + } + if ( (*iter)->hasMenu() ) + { + FMenu* menu = (*iter)->getMenu(); + if ( menu->hasSelectedListItem() ) + { + menu->unselectItemInList(); + menu->redraw(); + } + } } else { - (*iter)->unsetSelected(); - redraw(); + if ( mouse_y == 1 && (*iter)->isSelected() ) + { + (*iter)->unsetSelected(); + focus_changed = true; + } } - X = x2 + 1; ++iter; } + if ( focus_changed ) + redraw(); } } @@ -329,32 +337,40 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) if ( ! itemlist.empty() ) { std::vector::const_iterator iter, end; - int X = 1; iter = itemlist.begin(); end = itemlist.end(); while ( iter != end ) { - int x1, x2, txt_length; + int x1, x2, mouse_x, mouse_y; - x1 = X; - txt_length = int((*iter)->getTextLength()); - x2 = x1 + txt_length + 1; + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + mouse_x = ev->getX(); + mouse_y = ev->getY(); - if ( (*iter)->isSelected() ) + if ( mouse_x >= x1 + && mouse_x <= x2 + && mouse_y == 1 + && (*iter)->isSelected() ) { - int mouse_x = ev->getGlobalX(); - int mouse_y = ev->getGlobalY(); - if ( mouse_x < x1 || mouse_x > x2 || mouse_y != 1 ) - (*iter)->unsetSelected(); + if ( (*iter)->hasMenu() ) + { + FMenu* menu = (*iter)->getMenu(); + if ( ! menu->hasSelectedListItem() ) + { + menu->selectFirstItemInList(); + menu->redraw(); + } + } else { + (*iter)->unsetSelected(); + redraw(); (*iter)->processClicked(); } - redraw(); } - X = x2 + 1; ++iter; } } @@ -371,40 +387,46 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) { std::vector::const_iterator iter, end; bool focus_changed = false; - int X=1; iter = itemlist.begin(); end = itemlist.end(); while ( iter != end ) { - int x1, x2, txt_length; + int x1, x2, mouse_x, mouse_y; - x1 = X; - txt_length = int((*iter)->getTextLength()); - x2 = x1 + txt_length + 1; + x1 = (*iter)->getX(); + x2 = (*iter)->getX() + (*iter)->getWidth() - 1; + mouse_x = ev->getX(); + mouse_y = ev->getY(); - int mouse_x = ev->getGlobalX(); - int mouse_y = ev->getGlobalY(); if ( mouse_x >= x1 && mouse_x <= x2 && mouse_y == 1 ) { if ( ! (*iter)->isSelected() ) { - (*iter)->setSelected(); + (*iter)->setSelected(); focus_changed = true; } + if ( (*iter)->hasMenu() ) + { + FMenu* menu = (*iter)->getMenu(); + if ( menu->hasSelectedListItem() ) + { + menu->unselectItemInList(); + menu->redraw(); + } + } } else { - if ( (*iter)->isSelected() ) + if ( mouse_y == 1 && (*iter)->isSelected() ) { (*iter)->unsetSelected(); focus_changed = true; } } - X = x2 + 1; ++iter; } if ( focus_changed ) @@ -429,7 +451,7 @@ void FMenuBar::hide() memset(blank, ' ', uLong(screenWidth)); blank[screenWidth] = '\0'; - gotoxy (1, 1); + gotoxy (1,1); print (vmenubar, blank); delete[] blank; } @@ -451,6 +473,36 @@ void FMenuBar::cb_item_activated (FWidget* widget, void*) if ( menuitem->hasMenu() ) { - beep(); + //beep(); + FMenu* menu = menuitem->getMenu(); + if ( ! menu->isVisible() ) + { + menu->setVisible(); + menu->show(); + raiseWindow(menu); + menu->redraw(); + } + + updateTerminal(); + flush_out(); + } +} + +//---------------------------------------------------------------------- +void FMenuBar::cb_item_deactivated (FWidget* widget, void*) +{ + FMenuItem* menuitem = static_cast(widget); + + if ( menuitem->hasMenu() ) + { + //beep(); + FMenu* menu = menuitem->getMenu(); + if ( menu->isVisible() ) + menu->hide(); + + restoreVTerm (menu->getGeometryGlobalShadow()); + + updateTerminal(); + flush_out(); } } diff --git a/src/fmenubar.h b/src/fmenubar.h index 427dfe2a..94ea7cbb 100644 --- a/src/fmenubar.h +++ b/src/fmenubar.h @@ -45,8 +45,7 @@ class FMenuBar : public FWindow, public FMenuList { private: - bool mouse_down; - int x; + bool mouse_down; private: FMenuBar (const FMenuBar&); @@ -72,6 +71,7 @@ class FMenuBar : public FWindow, public FMenuList using FWidget::setGeometry; void setGeometry (int, int, int, int, bool = true); void cb_item_activated (FWidget*, void*); + void cb_item_deactivated (FWidget*, void*); private: friend class FMenuItem; diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index 1a07351c..b2f5d24d 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -100,7 +100,9 @@ void FMenuItem::init (FWidget* parent) { setSuperMenu( dynamic_cast(parent) ); superMenu()->insert(this); - dynamic_cast(parent)->menu_dimension(); + FMenuBar* menubar_ptr = dynamic_cast(parent); + if ( menubar_ptr ) + menubar_ptr->menu_dimension(); //addAccelerator (item->getKey(), item); @@ -109,12 +111,19 @@ void FMenuItem::init (FWidget* parent) "activate", _METHOD_CALLBACK (superMenu(), &FMenuBar::cb_item_activated) ); + this->addCallback + ( + "deactivate", + _METHOD_CALLBACK (superMenu(), &FMenuBar::cb_item_deactivated) + ); } else if ( isMenu(parent) ) // Parent is menu { setSuperMenu( dynamic_cast(parent) ); superMenu()->insert(this); - + FMenu* super_menu_ptr = dynamic_cast(parent); + if ( super_menu_ptr ) + super_menu_ptr->menu_dimension(); //addAccelerator (item->getKey(), item); @@ -123,6 +132,11 @@ void FMenuItem::init (FWidget* parent) "activate", _METHOD_CALLBACK (superMenu(), &FMenu::cb_menuitem_activated) ); + this->addCallback + ( + "deactivate", + _METHOD_CALLBACK (superMenu(), &FMenu::cb_menuitem_deactivated) + ); } } } @@ -138,15 +152,29 @@ uChar FMenuItem::getHotkey() length = text.getLength(); for (uInt i=0; i < length; i++) - if ( (i+1 < length) && (text[i] == '&') ) - return uChar(text[++i]); + { + try + { + if ( (i+1 < length) && (text[i] == '&') ) + return uChar(text[++i]); + } + catch (const std::out_of_range&) + { + return 0;; + } + } return 0; } //---------------------------------------------------------------------- bool FMenuItem::isMenuBar (FMenuList* ml) const { - return isMenuBar (dynamic_cast(ml)); + FWidget* menubar_ptr = dynamic_cast(ml); + + if ( menubar_ptr ) + return isMenuBar(menubar_ptr); + else + return false; } //---------------------------------------------------------------------- @@ -159,7 +187,12 @@ bool FMenuItem::isMenuBar (FWidget* w) const //---------------------------------------------------------------------- bool FMenuItem::isMenu (FMenuList* ml) const { - return isMenu (dynamic_cast(ml)); + FWidget* super_menu_ptr = dynamic_cast(ml); + + if ( super_menu_ptr ) + return isMenu(super_menu_ptr); + else + return false; } //---------------------------------------------------------------------- @@ -187,6 +220,12 @@ void FMenuItem::processActivate() emitCallback("activate"); } +//---------------------------------------------------------------------- +void FMenuItem::processDeactivate() +{ + emitCallback("deactivate"); +} + //---------------------------------------------------------------------- void FMenuItem::processClicked() { @@ -201,7 +240,7 @@ void FMenuItem::onAccel (FAccelEvent* ev) { unsetSelected(); FWidget* w = reinterpret_cast(superMenu()); - if ( isMenuBar(w) ) + if ( w && isMenuBar(w) ) w->redraw(); ev->accept(); } @@ -216,12 +255,15 @@ void FMenuItem::onMouseDown (FMouseEvent* ev) int b = ev->getButton(); p2 = p1 + getPos() - FPoint(1,1); ev = new FMouseEvent (MouseMove_Event, p2, g, b); - - if ( isMenu(super_menu) ) - dynamic_cast(super_menu)->onMouseDown(ev); - if ( isMenuBar(super_menu) ) - dynamic_cast(super_menu)->onMouseDown(ev); + if ( super_menu ) + { + if ( isMenu(super_menu) ) + dynamic_cast(super_menu)->onMouseDown(ev); + + if ( isMenuBar(super_menu) ) + dynamic_cast(super_menu)->onMouseDown(ev); + } delete ev; } @@ -236,11 +278,14 @@ void FMenuItem::onMouseUp (FMouseEvent* ev) p2 = p1 + getPos() - FPoint(1,1); ev = new FMouseEvent (MouseMove_Event, p2, g, b); - if ( isMenu(super_menu) ) - dynamic_cast(super_menu)->onMouseUp(ev); - - if ( isMenuBar(super_menu) ) - dynamic_cast(super_menu)->onMouseUp(ev); + if ( super_menu ) + { + if ( isMenu(super_menu) ) + dynamic_cast(super_menu)->onMouseUp(ev); + + if ( isMenuBar(super_menu) ) + dynamic_cast(super_menu)->onMouseUp(ev); + } delete ev; } @@ -255,11 +300,14 @@ void FMenuItem::onMouseMove (FMouseEvent* ev) p2 = p1 + getPos() - FPoint(1,1); ev = new FMouseEvent (MouseMove_Event, p2, g, b); - if ( isMenu(super_menu) ) - dynamic_cast(super_menu)->onMouseMove(ev); - - if ( isMenuBar(super_menu) ) - dynamic_cast(super_menu)->onMouseMove(ev); + if ( super_menu ) + { + if ( isMenu(super_menu) ) + dynamic_cast(super_menu)->onMouseMove(ev); + + if ( isMenuBar(super_menu) ) + dynamic_cast(super_menu)->onMouseMove(ev); + } delete ev; } @@ -275,7 +323,14 @@ void FMenuItem::setSelected() } //---------------------------------------------------------------------- -inline void FMenuItem::setText (FString& txt) +void FMenuItem::unsetSelected() +{ + selected = false; + processDeactivate(); +} + +//---------------------------------------------------------------------- +void FMenuItem::setText (FString& txt) { text = txt; text_length = text.getLength(); @@ -288,21 +343,11 @@ inline void FMenuItem::setText (FString& txt) //---------------------------------------------------------------------- inline void FMenuItem::setText (const std::string& txt) { - text = txt; - text_length = text.getLength(); - hotkey = getHotkey(); - if ( hotkey ) - text_length--; - setWidth(text_length); + setText (FString(txt)); } //---------------------------------------------------------------------- inline void FMenuItem::setText (const char* txt) { - text = txt; - text_length = text.getLength(); - hotkey = getHotkey(); - if ( hotkey ) - text_length--; - setWidth(text_length); + setText (FString(txt)); } diff --git a/src/fmenuitem.h b/src/fmenuitem.h index 10bbb316..d0b9447a 100644 --- a/src/fmenuitem.h +++ b/src/fmenuitem.h @@ -66,6 +66,7 @@ class FMenuItem : public FWidget FMenuList* superMenu() const; void setSuperMenu (FMenuList*); void processActivate(); + void processDeactivate(); void processClicked(); public: @@ -104,6 +105,7 @@ class FMenuItem : public FWidget private: friend class FMenuList; friend class FMenuBar; + friend class FMenu; }; #pragma pack(pop) @@ -125,10 +127,6 @@ inline void FMenuItem::unsetActive() inline bool FMenuItem::isActivated() const { return active; } -//---------------------------------------------------------------------- -inline void FMenuItem::unsetSelected() -{ selected = false; } - //---------------------------------------------------------------------- inline bool FMenuItem::isSelected() const { return selected; } diff --git a/src/foptimove.cpp b/src/foptimove.cpp index 4c44c5dc..fa32889f 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -357,9 +357,8 @@ int FOptiMove::relative_move ( char*& move if ( to_x != from_x ) // horizontal move { - char str[sizeof(move_buf)]; - char hmove[sizeof(move_buf)]; - hmove[0] = '\0'; + char str[sizeof(move_buf)] = {}; + char hmove[sizeof(move_buf)] = {}; htime = LONG_DURATION; if ( F_column_address.cap ) @@ -460,7 +459,7 @@ int FOptiMove::relative_move ( char*& move if ( move ) strcat (move, hmove); else - move = hmove; + strcpy (move, hmove); } return (vtime + htime); diff --git a/src/fstring.cpp b/src/fstring.cpp index d30bd17c..247561f5 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -155,8 +155,7 @@ FString::FString (const std::string& s) if ( wc_string ) { _replace( wc_string ); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } } } @@ -174,8 +173,7 @@ FString::FString (const char* s) if ( wc_string ) { _replace( wc_string ); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } } @@ -223,7 +221,7 @@ inline void FString::initLength (uInt len) { length = len; bufsize = FWDBUFFER + len + 1; - string = new wchar_t[bufsize]; + string = new wchar_t[bufsize](); wmemset(string, L'\0', bufsize); } } @@ -239,7 +237,7 @@ inline void FString::_replace (const wchar_t* s) try { - string = new wchar_t[bufsize]; + string = new wchar_t[bufsize](); } catch (const std::bad_alloc& ex) { @@ -265,7 +263,7 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) bufsize = FWDBUFFER + length + 1; try { - string = new wchar_t[bufsize]; + string = new wchar_t[bufsize](); } catch (const std::bad_alloc& ex) { @@ -296,7 +294,7 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) try { - sptr = new wchar_t[bufsize]; // generate new string + sptr = new wchar_t[bufsize](); // generate new string } catch (const std::bad_alloc& ex) { @@ -334,7 +332,7 @@ inline void FString::_remove (uInt pos, uInt len) try { - sptr = new wchar_t[bufsize]; // generate new string + sptr = new wchar_t[bufsize](); // generate new string } catch (const std::bad_alloc& ex) { @@ -361,7 +359,19 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const if ( ! s ) // handle NULL string return 0; if ( ! *s ) // handle empty string - return const_cast(""); + { + try + { + // Generate a empty string ("") + c_string = new char[1](); + } + catch (const std::bad_alloc& ex) + { + std::cerr << bad_alloc_str << " " << ex.what() << std::endl; + return 0; + } + return c_string; + } if ( c_string ) delete[](c_string); @@ -373,7 +383,7 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const try { - c_string = new char[dest_size]; + c_string = new char[dest_size](); // pre-initialiaze the whole string with '\0' memset (c_string, '\0', size_t(dest_size)); @@ -405,7 +415,18 @@ inline wchar_t* FString::c_to_wc_str (const char* s) const if ( ! s ) // handle NULL string return 0; if ( ! *s ) // handle empty string - return const_cast(L""); + { + try + { + // Generate a empty wide string (L"") + return (new wchar_t[1]()); + } + catch (const std::bad_alloc& ex) + { + std::cerr << bad_alloc_str << " " << ex.what() << std::endl; + return 0; + } + } size = int(strlen(s)) + 1; dest_size = size * int(CHAR_SIZE); @@ -415,7 +436,7 @@ inline wchar_t* FString::c_to_wc_str (const char* s) const try { - dest = new wchar_t[size]; + dest = new wchar_t[size](); // pre-initialiaze the whole string with '\0' wmemset (dest, L'\0', size_t(size)); } @@ -490,8 +511,7 @@ std::istream& operator >> (std::istream& instr, FString& s) if ( wc_str ) { s._replace (wc_str); - if ( *wc_str ) - delete[] wc_str; + delete[] wc_str; } return (instr); } @@ -550,8 +570,7 @@ FString& FString::operator = (const std::string& s) if ( wc_string ) { _replace( wc_string ); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } else length = bufsize = 0, string = 0; @@ -565,8 +584,7 @@ const FString& FString::operator = (const char* s) if ( wc_string ) { _replace( wc_string ); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } else length = bufsize = 0, string = 0; @@ -621,8 +639,7 @@ const FString& FString::operator += (const std::string& s) if ( wc_string ) { _insert (length, uInt(s.length()), wc_string); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } return (*this); } @@ -634,8 +651,7 @@ const FString& FString::operator += (const char* s) if ( wc_string ) { _insert (length, uInt(strlen(s)), wc_string); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } return (*this); } @@ -686,9 +702,9 @@ const FString FString::operator + (const std::string& s) wchar_t* wc_string = c_to_wc_str(s.c_str()); if ( ! wc_string ) return (tmp); - tmp._insert (length, uInt(wcslen(wc_string)), wc_string); - if ( *wc_string ) - delete[] wc_string; + tmp._insert (length, uInt(wcslen(wc_string)), wc_string); + delete[] wc_string; + return (tmp); } @@ -700,8 +716,8 @@ const FString FString::operator + (const char* s) if ( ! wc_string ) return (tmp); tmp._insert (length, uInt(wcslen(wc_string)), wc_string); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; + return (tmp); } @@ -878,7 +894,7 @@ FString& FString::sprintf (const char* format, ...) if ( len >= int(sizeof(buf)) ) { - buffer = new char[len+1]; + buffer = new char[len+1](); va_start (args, format); vsnprintf (buffer, uLong(len+1), format, args); va_end (args); @@ -888,8 +904,7 @@ FString& FString::sprintf (const char* format, ...) if ( wc_string ) { _replace(wc_string); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } if ( buffer != buf ) delete[] buffer; @@ -1282,8 +1297,7 @@ FString& FString::setString (const char* s) if ( wc_string ) { _replace (wc_string); - if ( *wc_string ) - delete[] wc_string; + delete[] wc_string; } return (*this); } diff --git a/src/fterm.cpp b/src/fterm.cpp index 92937990..5137e2b8 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -330,7 +330,7 @@ int FTerm::setScreenFont (uChar* fontdata, uInt count, font.data = fontdata; else { - const uInt bytes_per_line = uInt(ceil(font.width/8)); + const uInt bytes_per_line = font.width / 8; const size_t data_size = bytes_per_line * 32 * font.charcount; try @@ -776,8 +776,8 @@ int FTerm::parseKeyString ( char* buffer // look for meta keys for (int i=0; Fmetakey[i].string[0] != 0; i++) { - char* kmeta = Fmetakey[i].string; - len = (kmeta) ? int(strlen(kmeta)) : 0; + char* kmeta = Fmetakey[i].string; // The string is never null + len = int(strlen(kmeta)); if ( kmeta && strncmp(kmeta, buffer, uInt(len)) == 0 ) // found { if ( len == 2 && ( buffer[1] == 'O' @@ -805,7 +805,7 @@ int FTerm::parseKeyString ( char* buffer if ( utf8_input && (firstchar & 0xc0) == 0xc0 ) { - char utf8char[4] = { '\0' }; // init array with '\0' + char utf8char[4] = {}; // init array with '\0' if ((firstchar & 0xe0) == 0xc0) len = 2; else if ((firstchar & 0xf0) == 0xe0) @@ -948,6 +948,8 @@ void FTerm::init() stdin_no = fileno(stdin); stdout_no = fileno(stdout); stdin_status_flags = fcntl(stdin_no, F_GETFL); + if ( stdin_status_flags == -1 ) + std::abort(); term_name = ttyname(stdout_no); // look into /etc/ttytype for the type @@ -994,7 +996,7 @@ void FTerm::init() background_color_erase = false; x11_button_state = 0x03; - termtype = getenv("TERM"); + termtype = getenv(const_cast("TERM")); if ( ! termtype ) termtype = const_cast("vt100"); locale_xterm = getenv("XTERM_LOCALE"); @@ -1112,80 +1114,90 @@ void FTerm::init() FString temp = Sec_DA->right(Sec_DA->getLength() - 3); temp.remove(temp.getLength()-1, 1); std::vector Sec_DA_split = temp.split(';'); - FString* Sec_DA_components = &Sec_DA_split[0]; - switch ( Sec_DA_components[0].toInt() ) + if ( Sec_DA_split.size() >= 2 ) { - case 0: - if ( Sec_DA_components[1].toInt() == 136 ) - putty_terminal = true; // PuTTY - break; + FString* Sec_DA_components = &Sec_DA_split[0]; - case 1: - // also used by apple terminal - if ( strncmp(Sec_DA_components[1].c_str(), "2c", 2) == 0 ) - kterm_terminal = true; // kterm - else - { - gnome_terminal = true; // vte / gnome terminal - if ( color256 ) - termtype = const_cast("gnome-256color"); + switch ( Sec_DA_components[0].toInt() ) + { + case 0: + if ( Sec_DA_components[1] + && Sec_DA_components[1].toInt() == 136 ) + { + putty_terminal = true; // PuTTY + } + break; + + case 1: + // also used by apple terminal + if ( Sec_DA_components[1] + && strncmp(Sec_DA_components[1].c_str(), "2c", 2) == 0 ) + { + kterm_terminal = true; // kterm + } else - termtype = const_cast("gnome"); - } - break; - - case 32: // Tera Term - tera_terminal = true; - termtype = const_cast("teraterm"); - break; - - case 77: // mintty - mintty_terminal = true; - termtype = const_cast("xterm-256color"); - // application escape key mode - tputs ("\033[?7727h", 1, putchar); - fflush(stdout); - break; - - case 83: // screen - screen_terminal = true; - break; - - case 82: // rxvt - rxvt_terminal = true; - force_vt100 = true; // this rxvt terminal support on utf-8 - if ( strncmp(termtype, "rxvt-", 5) != 0 - || strncmp(termtype, "rxvt-cygwin-native", 5) == 0 ) - termtype = const_cast("rxvt-16color"); - break; - - case 85: // rxvt-unicode - rxvt_terminal = true; - urxvt_terminal = true; - if ( strncmp(termtype, "rxvt-", 5) != 0 ) - { - if ( color256 ) - termtype = const_cast("rxvt-256color"); - else - termtype = const_cast("rxvt"); - } - break; - - default: - break; + { + gnome_terminal = true; // vte / gnome terminal + if ( color256 ) + termtype = const_cast("gnome-256color"); + else + termtype = const_cast("gnome"); + } + break; + + case 32: // Tera Term + tera_terminal = true; + termtype = const_cast("teraterm"); + break; + + case 77: // mintty + mintty_terminal = true; + termtype = const_cast("xterm-256color"); + // application escape key mode + tputs ("\033[?7727h", 1, putchar); + fflush(stdout); + break; + + case 83: // screen + screen_terminal = true; + break; + + case 82: // rxvt + rxvt_terminal = true; + force_vt100 = true; // this rxvt terminal support on utf-8 + if ( strncmp(termtype, "rxvt-", 5) != 0 + || strncmp(termtype, "rxvt-cygwin-native", 5) == 0 ) + termtype = const_cast("rxvt-16color"); + break; + + case 85: // rxvt-unicode + rxvt_terminal = true; + urxvt_terminal = true; + if ( strncmp(termtype, "rxvt-", 5) != 0 ) + { + if ( color256 ) + termtype = const_cast("rxvt-256color"); + else + termtype = const_cast("rxvt"); + } + break; + + default: + break; + } } } // end of terminal detection - if ( strncmp(termtype, "xterm", 5) == 0 - || strncmp(termtype, "Eterm", 4) == 0 ) + if ( strncmp(termtype, const_cast("xterm"), 5) == 0 + || strncmp(termtype, const_cast("Eterm"), 4) == 0 ) xterm = true; else xterm = false; - if ( strncmp(termtype, "linux", 5) == 0 - || strncmp(termtype, "con", 3) == 0 ) + if ( strncmp(termtype, const_cast("linux"), 5) == 0 + || strncmp(termtype, const_cast("con"), 3) == 0 ) linux_terminal = true; else linux_terminal = false; @@ -2549,7 +2561,7 @@ FString FTerm::getXTermFont() if ( raw_mode && non_blocking_stdin ) { int n; - char temp[150] = { '\0' }; + char temp[150] = {}; tputs("\033]50;?\07", 1, putchar); // get font fflush(stdout); usleep(150000); // wait 150 ms @@ -2557,8 +2569,11 @@ FString FTerm::getXTermFont() n = int(read(fileno(stdin), &temp, sizeof(temp)-1)); // Esc \ = OSC String Terminator if ( n >= 2 && temp[n-1] == '\\' && temp[n-2] == 0x1b ) + { temp[n-2] = '\0'; - font = temp; + font = temp; + } + if ( font.getLength() > 6 ) font = font.mid(6, font.getLength()-1); } @@ -2576,7 +2591,7 @@ FString FTerm::getXTermTitle() if ( raw_mode && non_blocking_stdin ) { int n; - char temp[512] = { '\0' }; + char temp[512] = {}; tputs("\033[21t", 1, putchar); // get title fflush(stdout); usleep(150000); // wait 150 ms @@ -2584,8 +2599,11 @@ FString FTerm::getXTermTitle() n = int(read(fileno(stdin), &temp, sizeof(temp)-1)); // Esc \ = OSC String Terminator if ( n >= 2 && temp[n-1] == '\\' && temp[n-2] == 0x1b ) + { temp[n-2] = '\0'; - title = temp; + title = temp; + } + if ( title.getLength() > 3 ) title = title.right( title.getLength()-3 ); } @@ -3309,14 +3327,14 @@ bool FTerm::setNonBlockingInput(bool on) if ( on ) // make stdin non-blocking { stdin_status_flags |= O_NONBLOCK; - fcntl (stdin_no, F_SETFL, stdin_status_flags); - non_blocking_stdin = true; + if ( fcntl (stdin_no, F_SETFL, stdin_status_flags) != -1 ) + non_blocking_stdin = true; } else { stdin_status_flags &= ~O_NONBLOCK; - fcntl (stdin_no, F_SETFL, stdin_status_flags); - non_blocking_stdin = false; + if ( fcntl (stdin_no, F_SETFL, stdin_status_flags) != -1 ) + non_blocking_stdin = false; } return non_blocking_stdin; } @@ -3425,7 +3443,7 @@ FString FTerm::getAnswerbackMsg() if ( raw_mode ) { - char temp[10] = { '\0' }; + char temp[10] = {}; putchar(0x05); // send enquiry character fflush(stdout); usleep(150000); // wait 150 ms @@ -3443,7 +3461,7 @@ FString FTerm::getSecDA() if ( raw_mode ) { - char temp[16] = { '\0' }; + char temp[16] = {}; // get the secondary device attributes putchar(0x1b); // ESC putchar(0x5b); // [ diff --git a/test/string-operations.cpp b/test/string-operations.cpp index ec02daa0..4bde2a25 100644 --- a/test/string-operations.cpp +++ b/test/string-operations.cpp @@ -149,8 +149,10 @@ int main (int, char**) try { double double_num = FString("2.7182818284590452353").toDouble(); + std::ios_base::fmtflags save_flags = std::cout.flags(); std::cout << " toDouble: " << std::setprecision(11) << double_num << std::endl; + std::cout.flags(save_flags); } catch (const std::invalid_argument& ex) { @@ -210,10 +212,16 @@ int main (int, char**) FString index(5); // a string with five characters index = "index"; index[0] = L'I'; // write a wide character at position 0 - printf ( " index: [0] = %c ; [4] = %c\n" - , char(index[0]) - , char(index[4]) ); - + try + { + printf ( " index: [0] = %c ; [4] = %c\n" + , char(index[0]) + , char(index[4]) ); + } + catch (const std::out_of_range& ex) + { + std::cerr << "Out of Range error: " << ex.what() << std::endl; + } FString stringIterator = "iterator"; FString::iterator iter; iter = stringIterator.begin();