diff --git a/ChangeLog b/ChangeLog index 9f0ed22f..06a2e8bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-07-08 Markus Gans + * Better code readability: control structures (if/else, while, switch) + are now separated by a blank line. + 2016-07-06 Markus Gans * Stop terminal updates during processCloseWidget() is working diff --git a/src/fapp.cpp b/src/fapp.cpp index 7e687974..2c5d4ef8 100644 --- a/src/fapp.cpp +++ b/src/fapp.cpp @@ -68,8 +68,10 @@ FApplication::~FApplication() // destructor { if ( zero_point ) delete zero_point; + if ( event_queue ) delete event_queue; + rootObj = 0; } @@ -130,6 +132,7 @@ void FApplication::cmd_options () { FString encoding(optarg); encoding = encoding.toUpper(); + if ( encoding.includes("UTF8") || encoding.includes("VT100") || encoding.includes("PC") @@ -166,14 +169,18 @@ int FApplication::gpmEvent (bool clear) tv.tv_sec = 0; tv.tv_usec = 100000; // 100 ms result = select (max+1, &ifds, 0, 0, &tv); + if ( FD_ISSET(stdin_no, &ifds) ) { if ( clear ) FD_CLR (stdin_no, &ifds); + return keyboard_event; } + if ( clear && FD_ISSET(gpm_fd, &ifds) ) FD_CLR (gpm_fd, &ifds); + if (result > 0) return mouse_event; else @@ -193,8 +200,10 @@ inline bool FApplication::KeyPressed() tv.tv_sec = 0; tv.tv_usec = 100000; // 100 ms result = select (stdin_no+1, &ifds, 0, 0, &tv); + if ( FD_ISSET(stdin_no, &ifds) ) FD_CLR (stdin_no, &ifds); + return (result > 0); } @@ -219,6 +228,7 @@ void FApplication::processKeyboardEvent() else { widget = static_cast(main_widget); + if ( widget->numOfChildren() >= 1 ) widget->focusFirstChild(); } @@ -239,6 +249,7 @@ void FApplication::processKeyboardEvent() { gpmMouseEvent = false; int type = gpmEvent(); + switch ( type ) { case mouse_event: @@ -276,6 +287,7 @@ void FApplication::processKeyboardEvent() fifo_buf[fifo_offset] = k_buf[i]; fifo_offset++; } + fifo_in_use = true; } @@ -302,9 +314,12 @@ void FApplication::processKeyboardEvent() for (n=len; n < fifo_buf_size; n++) // Remove founded entry fifo_buf[n-len] = fifo_buf[n]; + n = fifo_buf_size-len-1; + for (; n < fifo_buf_size; n++) // Fill rest with '\0' fifo_buf[n-len] = '\0'; + input_data_pending = bool(fifo_buf[0] != '\0'); processMouseEvent(); } @@ -317,15 +332,21 @@ void FApplication::processKeyboardEvent() { sgr_mouse[n-3] = fifo_buf[n]; n++; + if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) len = n + 1; } + sgr_mouse[n-3] = '\0'; + for (n=len; n < fifo_buf_size; n++) // Remove founded entry fifo_buf[n-len] = fifo_buf[n]; + n = fifo_buf_size-len-1; + for (; n < fifo_buf_size; n++) // Fill rest with '\0' fifo_buf[n-len] = '\0'; + input_data_pending = bool(fifo_buf[0] != '\0'); processMouseEvent(); } @@ -338,15 +359,21 @@ void FApplication::processKeyboardEvent() { urxvt_mouse[n-2] = fifo_buf[n]; n++; + if ( fifo_buf[n] == 'M' || fifo_buf[n] == 'm' ) len = n + 1; } + urxvt_mouse[n-2] = '\0'; + for (n=len; n < fifo_buf_size; n++) // Remove founded entry fifo_buf[n-len] = fifo_buf[n]; + n = fifo_buf_size-len-1; + for (; n < fifo_buf_size; n++) // Fill rest with '\0' fifo_buf[n-len] = '\0'; + input_data_pending = bool(fifo_buf[0] != '\0'); processMouseEvent(); } @@ -366,8 +393,10 @@ void FApplication::processKeyboardEvent() { // keyboard accelerator FWidget* window = static_cast(active_window); + if ( ! window ) window = getRootWidget(); + if ( window && window->accelerator_list && ! window->accelerator_list->empty() ) @@ -380,27 +409,33 @@ void FApplication::processKeyboardEvent() { if ( quit_now || app_exit_loop ) break; + if ( iter->key == key ) { FAccelEvent a_ev (fc::Accelerator_Event, focus_widget); sendEvent (iter->object, &a_ev); break; }; + ++iter; } } } } // end of else } + fifo_offset = int(strlen(fifo_buf)); } + // send key up event FKeyEvent k_up_ev (fc::KeyUp_Event, key); sendEvent (widget, &k_up_ev); key = 0; } + std::fill_n (k_buf, sizeof(k_buf), '\0'); } + // special case: Esc key if ( fifo_in_use && fifo_offset == 1 @@ -542,8 +577,10 @@ bool FApplication::parseX11Mouse() if ( (x11_mouse[0] & key_shift) == key_shift ) b_state.shift_button = Pressed; + if ( (x11_mouse[0] & key_meta) == key_meta ) b_state.meta_button = Pressed; + if ( (x11_mouse[0] & key_ctrl) == key_ctrl ) b_state.control_button = Pressed; @@ -564,6 +601,7 @@ bool FApplication::parseX11Mouse() { return false; } + mouse->setPoint(x,y); x11_button_state = uChar(x11_mouse[0]); x11_mouse[0] = '\0'; @@ -606,6 +644,7 @@ bool FApplication::parseSGRMouse() { if ( *p < '0' || *p > '9') return false; + button = 10 * button + (*p - '0'); p++; } @@ -621,6 +660,7 @@ bool FApplication::parseSGRMouse() { if ( *p < '0' || *p > '9') return false; + y = uChar(10 * y + (*p - '0')); } @@ -629,8 +669,10 @@ bool FApplication::parseSGRMouse() if ( (button & key_shift) == key_shift ) b_state.shift_button = Pressed; + if ( (button & key_meta) == key_meta ) b_state.meta_button = Pressed; + if ( (button & key_ctrl) == key_ctrl ) b_state.control_button = Pressed; @@ -715,6 +757,7 @@ bool FApplication::parseSGRMouse() break; } } + if ( *mouse == newMousePosition && b_state.wheel_up != Pressed && b_state.wheel_down != Pressed @@ -722,6 +765,7 @@ bool FApplication::parseSGRMouse() { return false; } + mouse->setPoint(x,y); x11_button_state = uChar(((*p & 0x20) << 2) + button); sgr_mouse[0] = '\0'; @@ -769,6 +813,7 @@ bool FApplication::parseUrxvtMouse() { if ( *p < '0' || *p > '9') return false; + button = 10 * button + (*p - '0'); p++; } @@ -778,10 +823,12 @@ bool FApplication::parseUrxvtMouse() p++; x_neg = true; } + while ( *p && *p != ';' ) { if ( *p < '0' || *p > '9') return false; + x = uChar(10 * x + (*p - '0')); p++; } @@ -791,20 +838,25 @@ bool FApplication::parseUrxvtMouse() p++; y_neg = true; } + while ( *p && *p != 'M' ) { if ( *p < '0' || *p > '9') return false; + y = uChar(10 * y + (*p - '0')); p++; } if ( x_neg || x == 0 ) x = 1; + if ( y_neg || y == 0 ) y = 1; + if ( x > term->getWidth() ) x = uChar(term->getWidth()); + if ( y > term->getHeight() ) y = uChar(term->getHeight()); @@ -813,8 +865,10 @@ bool FApplication::parseUrxvtMouse() if ( (button & key_shift) == key_shift ) b_state.shift_button = Pressed; + if ( (button & key_meta) == key_meta ) b_state.meta_button = Pressed; + if ( (button & key_ctrl) == key_ctrl ) b_state.control_button = Pressed; @@ -834,6 +888,7 @@ bool FApplication::parseUrxvtMouse() { return false; } + mouse->setPoint(x,y); x11_button_state = uChar(button); urxvt_mouse[0] = '\0'; @@ -849,6 +904,7 @@ bool FApplication::processGpmEvent() if ( Gpm_GetEvent(&gpm_ev) == 1 ) { Gpm_FitEvent (&gpm_ev); + if ( gpm_ev.type & GPM_DRAG && gpm_ev.wdx == 0 && gpm_ev.wdy == 0 ) b_state.mouse_moved = true; @@ -868,35 +924,45 @@ bool FApplication::processGpmEvent() else b_state.left_button = Pressed; } + if ( gpm_ev.buttons & GPM_B_MIDDLE ) b_state.middle_button = Pressed; + if ( gpm_ev.buttons & GPM_B_RIGHT ) b_state.right_button = Pressed; + if ( gpm_ev.buttons & GPM_B_UP ) b_state.wheel_up = Pressed; + if ( gpm_ev.buttons & GPM_B_DOWN ) b_state.wheel_down = Pressed; // keyboard modifiers if ( gpm_ev.modifiers & (1 << KG_SHIFT) ) b_state.shift_button = Pressed; + if ( gpm_ev.modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)) ) b_state.meta_button = Pressed; + if ( gpm_ev.modifiers & (1 << KG_CTRL) ) b_state.control_button = Pressed; + break; case GPM_UP: if ( gpm_ev.buttons & GPM_B_LEFT ) b_state.left_button = Released; + if ( gpm_ev.buttons & GPM_B_MIDDLE ) b_state.middle_button = Released; + if ( gpm_ev.buttons & GPM_B_RIGHT ) b_state.right_button = Released; default: break; } + mouse->setPoint(gpm_ev.x, gpm_ev.y); if ( gpmEvent(false) == mouse_event ) @@ -909,6 +975,7 @@ bool FApplication::processGpmEvent() return true; } + gpmMouseEvent = false; return false; } @@ -962,6 +1029,7 @@ void FApplication::processMouseEvent() || b_state.wheel_down == Pressed ) ) { FWidget* window = FWindow::getWindowWidgetAt (*mouse); + if ( window ) { FWidget* child = childWidgetAt (window, *mouse); @@ -984,8 +1052,10 @@ void FApplication::processMouseEvent() // No widget was been clicked if ( ! clicked_widget ) FWindow::switchToPrevWindow(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -1000,14 +1070,17 @@ void FApplication::processMouseEvent() { if ( statusBar() ) statusBar()->clearMessage(); + menuBar()->resetMenu(); menuBar()->redraw(); // No widget was been clicked if ( ! clicked_widget ) FWindow::switchToPrevWindow(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -1020,8 +1093,10 @@ void FApplication::processMouseEvent() if ( b_state.shift_button == Pressed ) key_state |= fc::ShiftButton; + if ( b_state.meta_button == Pressed ) key_state |= fc::MetaButton; + if ( b_state.control_button == Pressed ) key_state |= fc::ControlButton; @@ -1037,6 +1112,7 @@ void FApplication::processMouseEvent() , fc::LeftButton | key_state ); sendEvent (clicked_widget, &m_down_ev); } + if ( b_state.right_button == Pressed ) { FMouseEvent m_down_ev ( fc::MouseMove_Event @@ -1045,6 +1121,7 @@ void FApplication::processMouseEvent() , fc::RightButton | key_state ); sendEvent (clicked_widget, &m_down_ev); } + if ( b_state.middle_button == Pressed ) { FMouseEvent m_down_ev ( fc::MouseMove_Event @@ -1113,6 +1190,7 @@ void FApplication::processMouseEvent() , *mouse , fc::MiddleButton | key_state ); sendEvent (clicked_widget, &m_down_ev); + // gnome-terminal sends no released on middle click if ( gnome_terminal ) clicked_widget = 0; @@ -1124,9 +1202,13 @@ void FApplication::processMouseEvent() , *mouse , fc::MiddleButton | key_state ); FWidget* released_widget = clicked_widget; + if ( b_state.right_button != Pressed && b_state.left_button != Pressed ) - clicked_widget = 0; + { + clicked_widget = 0; + } + sendEvent (released_widget, &m_up_ev); } } @@ -1152,6 +1234,7 @@ void FApplication::processMouseEvent() clicked_widget = 0; sendEvent (scroll_over_widget, &wheel_ev); } + } #ifdef F_HAVE_LIBGPM @@ -1187,6 +1270,7 @@ int FApplication::processTimerEvent() if ( ! timer_list ) return 0; + if ( timer_list->empty() ) return 0; @@ -1245,6 +1329,7 @@ void FApplication::processTerminalUpdate() void FApplication::processCloseWidget() { updateTerminal(false); + if ( close_widget && ! close_widget->empty() ) { widgetList::iterator iter; @@ -1255,6 +1340,7 @@ void FApplication::processCloseWidget() delete *iter; ++iter; } + close_widget->clear(); } updateTerminal(true); @@ -1314,6 +1400,7 @@ int FApplication::exec() // run showCursor(); flush_out(); } + enter_loop(); return quit_code; } @@ -1327,12 +1414,12 @@ int FApplication::enter_loop() // event loop old_app_exit_loop = app_exit_loop; app_exit_loop = false; + while ( ! quit_now && ! app_exit_loop ) processNextEvent(); + app_exit_loop = old_app_exit_loop; - loop_level--; - return 0; } @@ -1347,8 +1434,10 @@ void FApplication::exit (int retcode) { if ( ! rootObj ) // no global app object return; + if ( quit_now ) // don't overwrite quit code return; + quit_now = true; quit_code = retcode; } @@ -1470,6 +1559,7 @@ bool FApplication::removeQueuedEvent(FObject* receiver) if ( ! eventInQueue() ) return false; + if ( ! receiver ) return false; @@ -1486,5 +1576,6 @@ bool FApplication::removeQueuedEvent(FObject* receiver) else ++iter; } + return retval; } diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 5a60d43f..7f8c3750 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -92,6 +92,7 @@ uChar FButton::getHotkey() return 0;; } } + return 0; } @@ -99,6 +100,7 @@ uChar FButton::getHotkey() void FButton::setHotkeyAccelerator() { int hotkey = getHotkey(); + if ( hotkey ) { if ( isalpha(hotkey) || isdigit(hotkey) ) @@ -132,6 +134,7 @@ void FButton::draw() register wchar_t* dest; wchar_t* ButtonText; FString txt; + int active_focus; int d, i, j, x, mono_offset, margin; int length, hotkeypos, hotkey_offset, space; bool is_ActiveFocus, is_Active, is_Focus, is_Flat; @@ -151,30 +154,34 @@ void FButton::draw() src = const_cast(txt.wc_str()); dest = const_cast(ButtonText); - int active_focus = fc::active + fc::focus; + active_focus = fc::active + fc::focus; is_ActiveFocus = ((flags & active_focus) == active_focus); is_Active = ((flags & fc::active) != 0); is_Focus = ((flags & fc::focus) != 0); is_Flat = isFlat(); is_NonFlatShadow = ((flags & (fc::shadow+fc::flat)) == fc::shadow); is_NoUnderline = ((flags & fc::no_underline) != 0); - setUpdateVTerm(false); + if ( isMonochron() ) setReverse(true); + if ( button_down && click_animation ) { // noshadow + indent one character to the right if ( is_Flat ) clearFlatBorder(); + clearShadow(); setColor ( getParentWidget()->getForegroundColor() , getParentWidget()->getBackgroundColor() ); + for (int y=1; y <= height; y++) { gotoxy (xpos+xmin-1, ypos+ymin-2+y); print (' '); // clear one left █ } + d = 1; } else @@ -203,8 +210,10 @@ void FButton::draw() i++; src++; } + *dest++ = *src++; } + if ( hotkeypos != -1 ) hotkey_offset = 1; @@ -221,12 +230,14 @@ void FButton::draw() if ( margin == 1 ) { setColor (foregroundColor, button_bg); + for (int y=0; y < height; y++) { gotoxy (xpos+xmin-1+d, ypos+ymin-1+y); print (space); // full block █ } } + if ( ! button_down ) drawFlatBorder(); } @@ -234,6 +245,7 @@ void FButton::draw() { setColor (button_bg, getParentWidget()->getBackgroundColor()); gotoxy (xpos+xmin-1+d, ypos+ymin-1); + for (int y=1; y <= height; y++) { // Cygwin terminal use IBM Codepage 850 @@ -243,6 +255,7 @@ void FButton::draw() print (0xdb); else print (fc::RightHalfBlock); // ▐ + gotoxy (xpos+xmin-1+d, ypos+ymin-1+y); } } @@ -254,12 +267,15 @@ void FButton::draw() // clear the right █ from button down setColor ( getParentWidget()->getForegroundColor() , getParentWidget()->getBackgroundColor() ); + for (int y=1; y <= height; y++) { if ( isMonochron() ) setReverse(true); + gotoxy (xpos+xmin-1+width, ypos+ymin-2+y); print (' '); // clear right + if ( isMonochron() ) setReverse(false); } @@ -297,15 +313,21 @@ void FButton::draw() if ( (z == hotkeypos) && is_Active ) { setColor (button_hotkey_fg, button_bg); + if ( ! is_ActiveFocus && getMaxColor() < 16 ) setBold(); + if ( ! is_NoUnderline ) setUnderline(); + print ( ButtonText[z] ); + if ( ! is_ActiveFocus && getMaxColor() < 16 ) unsetBold(); + if ( ! is_NoUnderline ) unsetUnderline(); + setColor (button_fg, button_bg); } else @@ -325,12 +347,14 @@ void FButton::draw() for (i=0; i < j; i++) { gotoxy (xpos+xmin+d, ypos+ymin-1+i); + for (int z=1; z < width; z++) print (space); // █ } for (i=j+1; i < height; i++) { gotoxy (xpos+xmin+d, ypos+ymin-1+i); + for (int z=1; z < width; z++) print (space); // █ } @@ -357,6 +381,7 @@ void FButton::draw() { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) { statusBar()->setMessage(msg); @@ -423,6 +448,7 @@ void FButton::setFocusForegroundColor (short color) // valid colors -1..254 if ( color == fc::Default || color >> 8 == 0 ) button_focus_fg = color; + updateButtonColor(); } @@ -432,6 +458,7 @@ void FButton::setFocusBackgroundColor (short color) // valid colors -1..254 if ( color == fc::Default || color >> 8 == 0 ) button_focus_bg = color; + updateButtonColor(); } @@ -441,6 +468,7 @@ void FButton::setInactiveForegroundColor (short color) // valid colors -1..254 if ( color == fc::Default || color >> 8 == 0 ) button_inactive_fg = color; + updateButtonColor(); } @@ -450,6 +478,7 @@ void FButton::setInactiveBackgroundColor (short color) // valid colors -1..254 if ( color == fc::Default || color >> 8 == 0 ) button_inactive_bg = color; + updateButtonColor(); } @@ -461,22 +490,22 @@ void FButton::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); - s = hasShadow() ? 1 : 0; f = isFlat() ? 1 : 0; size = width + s + (f << 1); blank = new char[size+1]; memset(blank, ' ', uLong(size)); blank[size] = '\0'; + for (int y=0; y < height+s+(f << 1); y++) { gotoxy (xpos+xmin-1-f, ypos+ymin-1+y-f); print (blank); } + delete[] blank; } @@ -487,6 +516,7 @@ bool FButton::setNoUnderline (bool on) flags |= fc::no_underline; else flags &= ~fc::no_underline; + return on; } @@ -505,6 +535,7 @@ bool FButton::setEnable (bool on) flags &= ~fc::active; delAccelerator(); } + updateButtonColor(); return on; } @@ -524,6 +555,7 @@ bool FButton::setFocus (bool on) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) statusBar()->setMessage(msg); } @@ -536,6 +568,7 @@ bool FButton::setFocus (bool on) if ( isEnabled() && statusBar() ) statusBar()->clearMessage(); } + updateButtonColor(); return on; } @@ -553,12 +586,13 @@ bool FButton::setFlat (bool on) //---------------------------------------------------------------------- bool FButton::setShadow (bool on) { - if ( on + if ( on && (Encoding != fc::VT100 || isTeraTerm() ) && Encoding != fc::ASCII ) flags |= fc::shadow; else flags &= ~fc::shadow; + return on; } @@ -570,6 +604,7 @@ bool FButton::setDown (bool on) button_down = on; redraw(); } + return on; } @@ -617,12 +652,16 @@ void FButton::onMouseDown (FMouseEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); } + FPoint gPos = ev->getGlobalPos(); + if ( getGeometryGlobal().contains(gPos) ) setDown(); } @@ -636,6 +675,7 @@ void FButton::onMouseUp (FMouseEvent* ev) if ( button_down ) { setUp(); + if ( getGeometryGlobal().contains(ev->getGlobalPos()) ) processClick(); } @@ -648,6 +688,7 @@ void FButton::onMouseMove (FMouseEvent* ev) return; FPoint gPos = ev->getGlobalPos(); + if ( click_animation ) { if ( getGeometryGlobal().contains(gPos) ) @@ -675,17 +716,21 @@ void FButton::onAccel (FAccelEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + if ( click_animation ) setDown(); else redraw(); + if ( statusBar() ) statusBar()->drawMessage(); } else if ( click_animation ) setDown(); + if ( click_animation ) addTimer(click_time); @@ -718,5 +763,6 @@ void FButton::setText (const FString& txt) text = txt; else text = ""; + detectHotkey(); } diff --git a/src/fbuttongroup.cpp b/src/fbuttongroup.cpp index 4719dafc..22a5b59b 100644 --- a/src/fbuttongroup.cpp +++ b/src/fbuttongroup.cpp @@ -64,7 +64,6 @@ void FButtonGroup::init() foregroundColor = wc.label_fg; backgroundColor = wc.label_bg; - buttonlist.clear(); // no buttons yet } @@ -99,12 +98,16 @@ void FButtonGroup::directFocus() FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); (*iter)->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + getFocusWidget()->redraw(); } + break; } + ++iter; } } @@ -115,8 +118,10 @@ void FButtonGroup::directFocus() FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); focusFirstChild(); + if ( focused_widget ) focused_widget->redraw(); + getFocusWidget()->redraw(); } } @@ -134,14 +139,20 @@ void FButtonGroup::directFocus() void FButtonGroup::draw() { setUpdateVTerm(false); + if ( isMonochron() ) setReverse(true); + setColor (foregroundColor, backgroundColor); + if ( border ) drawBorder(); + drawLabel(); + if ( isMonochron() ) setReverse(false); + setUpdateVTerm(true); } @@ -246,16 +257,21 @@ void FButtonGroup::drawLabel() if ( (z == hotkeypos) && isActive ) { setColor (wc.label_hotkey_fg, wc.label_hotkey_bg); + if ( ! isNoUnderline ) setUnderline(); + print ( LabelText[z] ); + if ( ! isNoUnderline ) unsetUnderline(); + setColor (wc.label_emphasis_fg, wc.label_bg); } else print ( LabelText[z] ); } + delete[] LabelText; } @@ -267,6 +283,7 @@ void FButtonGroup::hide() short fg, bg; char* blank; FWidget::hide(); + if ( ! buttonlist.empty() ) { FButtonGroup::FButtonList::const_iterator iter, end; @@ -288,11 +305,13 @@ void FButtonGroup::hide() blank = new char[size+1]; memset(blank, ' ', uLong(size)); blank[size] = '\0'; + for (int y=0; y < height; y++) { gotoxy (xpos+xmin-1, ypos+ymin-1+y); print (blank); } + delete[] blank; } @@ -332,7 +351,6 @@ void FButtonGroup::remove (FToggleButton* button) { iter = buttonlist.erase(iter); button->setGroup(0); - button->delCallback(this); break; } @@ -349,6 +367,7 @@ void FButtonGroup::cb_buttonToggled (FWidget* widget, void*) if ( ! button->isChecked() ) return; + if ( buttonlist.empty() ) return; @@ -362,9 +381,11 @@ void FButtonGroup::cb_buttonToggled (FWidget* widget, void*) && isRadioButton(*iter) ) { (*iter)->unsetChecked(); + if ( (*iter)->isVisible() && (*iter)->isShown() ) (*iter)->redraw(); } + ++iter; } } @@ -382,9 +403,11 @@ FToggleButton* FButtonGroup::getFirstButton() { if ( (*iter)->isEnabled() && (*iter)->acceptFocus() ) return (*iter); + ++iter; } } + return 0; } @@ -396,14 +419,17 @@ FToggleButton* FButtonGroup::getLastButton() FButtonGroup::FButtonList::const_iterator iter, begin; begin = buttonlist.begin(); iter = buttonlist.end(); + do { --iter; + if ( (*iter)->isEnabled() && (*iter)->acceptFocus() ) return (*iter); } while ( iter != begin ); } + return 0; } @@ -420,9 +446,11 @@ bool FButtonGroup::hasFocusedButton() { if ( (*iter)->hasFocus() ) return true; + ++iter; } } + return false; } @@ -439,9 +467,11 @@ bool FButtonGroup::hasCheckedButton() { if ( (*iter)->isChecked() ) return true; + ++iter; } } + return false; } @@ -450,6 +480,7 @@ void FButtonGroup::onMouseDown (FMouseEvent* ev) { if ( ev->getButton() != fc::LeftButton ) return; + directFocus(); } @@ -477,15 +508,20 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) in_ev->ignore(); FWidget* prev_element = getFocusWidget(); (*iter)->setFocus(); + if ( prev_element ) prev_element->redraw(); + (*iter)->redraw(); } + break; } + ++iter; } } + if ( in_ev->isAccepted() ) { if ( in_ev->getFocusType() == fc::FocusNextWidget ) @@ -493,8 +529,10 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) in_ev->ignore(); FWidget* prev_element = getFocusWidget(); focusFirstChild(); + if ( prev_element ) prev_element->redraw(); + getFocusWidget()->redraw(); } else if ( in_ev->getFocusType() == fc::FocusPreviousWidget ) @@ -502,11 +540,14 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) in_ev->ignore(); FWidget* prev_element = getFocusWidget(); focusLastChild(); + if ( prev_element ) prev_element->redraw(); + getFocusWidget()->redraw(); } } + if ( statusBar() ) { statusBar()->drawMessage(); @@ -534,6 +575,7 @@ bool FButtonGroup::setEnable (bool on) flags &= ~fc::active; delAccelerator(); } + return on; } @@ -544,6 +586,7 @@ bool FButtonGroup::setBorder(bool on) border = true; else border = false; + return on; } @@ -551,6 +594,7 @@ bool FButtonGroup::setBorder(bool on) void FButtonGroup::setText (const FString& txt) { text = txt; + if ( isEnabled() ) { delAccelerator(); diff --git a/src/fcheckbox.cpp b/src/fcheckbox.cpp index 4c0e0836..de9db484 100644 --- a/src/fcheckbox.cpp +++ b/src/fcheckbox.cpp @@ -44,7 +44,6 @@ void FCheckBox::draw() drawCheckButton(); drawLabel(); setUpdateVTerm(true); - FToggleButton::draw(); } @@ -64,6 +63,7 @@ void FCheckBox::drawCheckButton() else setReverse(true); } + if ( checked ) { if ( isNewFont() ) @@ -86,6 +86,7 @@ void FCheckBox::drawCheckButton() print (']'); } } + if ( isMonochron() ) setReverse(false); } diff --git a/src/fcheckmenuitem.cpp b/src/fcheckmenuitem.cpp index 37531cfe..39a217bc 100644 --- a/src/fcheckmenuitem.cpp +++ b/src/fcheckmenuitem.cpp @@ -53,6 +53,7 @@ void FCheckMenuItem::init (FWidget* parent) if ( isMenu(parent) ) // Parent is menu { FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) menu_ptr->has_checkable_items = true; } diff --git a/src/fdialog.cpp b/src/fdialog.cpp index 7f39b58d..64433619 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -44,17 +44,18 @@ FDialog::FDialog (const FString& txt, FWidget* parent) //---------------------------------------------------------------------- FDialog::~FDialog() // destructor { + FApplication* fapp; + delete accelerator_list; accelerator_list = 0; activatePrevWindow(); delWindow(this); + fapp = static_cast(getRootWidget()); - FApplication* fapp = static_cast(getRootWidget()); if ( ! fapp->quit_now ) { const FRect& geometry = getGeometryGlobalShadow(); restoreVTerm (geometry); - getParentWidget()->redraw(); } @@ -67,10 +68,13 @@ FDialog::~FDialog() // destructor while ( iter != end ) { putArea ((*iter)->getGlobalPos(), (*iter)->getVWin()); + if ( ! maximized && ((*iter)->getFlags() & fc::shadow) != 0 ) static_cast(*iter)->drawDialogShadow(); + ++iter; } + setFocusWidget(0); updateTerminal(); flush_out(); @@ -80,10 +84,13 @@ FDialog::~FDialog() // destructor { if ( vwin->changes != 0 ) delete[] vwin->changes; + if ( vwin->text != 0 ) delete[] vwin->text; + delete vwin; } + if ( isModal() ) unsetModal(); } @@ -92,7 +99,10 @@ FDialog::~FDialog() // destructor //---------------------------------------------------------------------- void FDialog::init() { - FWidget* rootObj = getRootWidget(); + FMenuItem* close_item; + FWidget* old_focus; + FWidget* rootObj = getRootWidget(); + xmin = 1 + rootObj->getLeftPadding(); ymin = 1 + rootObj->getTopPadding(); xmax = rootObj->getWidth(); @@ -120,28 +130,30 @@ void FDialog::init() if ( hasFocus() ) flags |= fc::focus; + if ( isEnabled() ) flags |= fc::active; - FWidget* old_focus = FWidget::getFocusWidget(); + old_focus = FWidget::getFocusWidget(); + if ( old_focus ) { setFocus(); old_focus->redraw(); } - accelerator_list = new Accelerators(); + accelerator_list = new Accelerators(); dialog_menu = new FMenu ("-", this); dialog_menu->move (xpos, ypos+1); - dgl_menuitem = dialog_menu->getItem(); + if ( dgl_menuitem ) { dgl_menuitem->ignorePadding(); dgl_menuitem->unsetFocusable(); } - FMenuItem* close_item = new FMenuItem ("&Close", dialog_menu); + close_item = new FMenuItem ("&Close", dialog_menu); close_item->setStatusbarMessage ("Close window"); close_item->addCallback @@ -163,10 +175,12 @@ void FDialog::drawBorder() if ( isNewFont() ) { short fg; + if ( ! isRootWidget() ) fg = getParentWidget()->getForegroundColor(); else fg = wc.term_fg; + for (int y=y1; y <= y2; y++) { setColor (fg, backgroundColor); @@ -177,6 +191,7 @@ void FDialog::drawBorder() // border right⎹ print (fc::NF_rev_border_line_right); } + if ( (flags & fc::shadow) == 0 ) { setColor (fg, backgroundColor); @@ -189,19 +204,23 @@ void FDialog::drawBorder() // lower right corner border ⎦ print (fc::NF_rev_border_corner_lower_right); } + } else { gotoxy (x1, y1); print (fc::BoxDrawingsDownAndRight); // ┌ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ - print (fc::BoxDrawingsDownAndLeft); // ┐ + print (fc::BoxDrawingsDownAndLeft); // ┐ gotoxy (x1, y2); print (fc::BoxDrawingsUpAndRight); // └ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::BoxDrawingsUpAndLeft); // ┘ for (int y=y1+1; y < y2; y++) @@ -211,6 +230,7 @@ void FDialog::drawBorder() gotoxy (x2, y); print (fc::BoxDrawingsVertical); // │ } + } } @@ -223,6 +243,7 @@ void FDialog::drawTitleBar() // draw the title button gotoxy (xpos+xmin-1, ypos+ymin-1); setColor (wc.titlebar_button_fg, wc.titlebar_button_bg); + if ( isMonochron() ) { if ( isActiveWindow() ) @@ -241,25 +262,30 @@ void FDialog::drawTitleBar() else if ( isMonochron() ) { print ('['); + if ( dgl_menuitem ) print (dgl_menuitem->getText()); else print ('-'); + print (']'); } else { print (' '); + if ( dgl_menuitem ) print (dgl_menuitem->getText()); else print ('-'); + print (' '); } // fill with spaces (left of the title) if ( getMaxColor() < 16 ) setBold(); + if ( isActiveWindow() || dialog_menu->isVisible() ) setColor (wc.titlebar_active_fg, wc.titlebar_active_bg); else @@ -281,6 +307,7 @@ void FDialog::drawTitleBar() if ( getMaxColor() < 16 ) unsetBold(); + if ( isMonochron() ) setReverse(false); @@ -299,8 +326,10 @@ void FDialog::leaveMenu() raiseWindow(); getFocusWidget()->setFocus(); redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -337,6 +366,7 @@ void FDialog::drawDialogShadow() FOptiAttr::char_data ch; // left of the shadow ▀▀ gotoxy (xpos+xmin-1, ypos+ymin-1+height); + for (int x=0; x <= 1; x++) { ch = getCoveredCharacter (xpos+xmin-1+x, ypos+ymin-1+height, this); @@ -348,12 +378,12 @@ void FDialog::drawDialogShadow() } else { + FOptiAttr::char_data ch; + if ( isMonochron() ) return; drawShadow(); - - FOptiAttr::char_data ch; ch = getCoveredCharacter (xpos+xmin-1, ypos+ymin-1+height, this); // left of the shadow ▀▀ gotoxy (xpos+xmin-1, ypos+ymin-1+height); @@ -370,33 +400,44 @@ void FDialog::drawDialogShadow() if ( ch.bold ) setBold(); + if ( ch.dim ) setDim(); + if ( ch.italic ) setItalic(); + if ( ch.underline ) setUnderline(); + if ( ch.blink ) setBlink(); + if ( ch.reverse ) setReverse(); + if ( ch.standout ) setStandout(); + if ( ch.invisible ) setInvisible(); + if ( ch.protect ) setProtected(); + if ( ch.crossed_out ) setCrossedOut(); + if ( ch.dbl_underline ) setDoubleUnderline(); + if ( ch.alt_charset ) setAltCharset (true); + if ( ch.pc_charset ) setPCcharset (true); print (ch.code); - setNormal(); } } @@ -414,9 +455,9 @@ void FDialog::draw() } setUpdateVTerm(false); - // fill the background setColor (foregroundColor, backgroundColor); + if ( isMonochron() ) setReverse(true); @@ -469,8 +510,10 @@ void FDialog::draw() } } } + if ( isMonochron() ) setReverse(false); + setUpdateVTerm(true); } @@ -500,6 +543,7 @@ void FDialog::onKeyPress (FKeyEvent* ev) || ev->key() == fc::Fkey_escape_mintty ) { ev->accept(); + if ( isModal() ) done (FDialog::Reject); else @@ -515,13 +559,15 @@ void FDialog::onMouseDown (FMouseEvent* ev) if ( ev->getButton() == fc::LeftButton ) { + bool has_raised; + // click on titlebar or window: raise + activate if ( mouse_x >= 4 && mouse_x <= width && mouse_y == 1 ) TitleBarClickPos.setPoint (ev->getGlobalX(), ev->getGlobalY()); else TitleBarClickPos.setPoint (0,0); - bool has_raised = raiseWindow(); + has_raised = raiseWindow(); if ( ! isActiveWindow() ) { @@ -532,6 +578,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) { focus_widget->setFocus(); focus_widget->redraw(); + if ( old_focus ) old_focus->redraw(); } @@ -540,8 +587,10 @@ void FDialog::onMouseDown (FMouseEvent* ev) if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); } + if ( has_raised ) redraw(); @@ -577,10 +626,12 @@ void FDialog::onMouseDown (FMouseEvent* ev) { FWidget* old_focus = FWidget::getFocusWidget(); setActiveWindow(this); + if ( focus_widget ) { focus_widget->setFocus(); focus_widget->redraw(); + if ( old_focus ) old_focus->redraw(); } @@ -589,6 +640,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); } } @@ -605,10 +657,12 @@ void FDialog::onMouseDown (FMouseEvent* ev) { FWidget* old_focus = FWidget::getFocusWidget(); setActiveWindow(this); + if ( focus_widget ) { focus_widget->setFocus(); focus_widget->redraw(); + if ( old_focus ) old_focus->redraw(); } @@ -617,6 +671,7 @@ void FDialog::onMouseDown (FMouseEvent* ev) if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); } else if ( has_lowered ) @@ -656,11 +711,15 @@ void FDialog::onMouseUp (FMouseEvent* ev) FMenuItem* first_item; dialog_menu->selectFirstItem(); first_item = dialog_menu->getSelectedItem(); + if ( first_item ) first_item->setFocus(); + dialog_menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -712,8 +771,8 @@ void FDialog::onMouseDoubleClick (FMouseEvent* ev) x = xpos + xmin - 1; y = ypos + ymin - 1; FRect title_button(x, y, 3, 1); - FPoint gPos = ev->getGlobalPos(); + if ( title_button.contains(gPos) ) { dialog_menu->unselectItem(); @@ -774,6 +833,7 @@ void FDialog::onWindowRaised (FEvent*) if ( ! window_list ) return; + if ( window_list->empty() ) return; @@ -783,10 +843,12 @@ void FDialog::onWindowRaised (FEvent*) while ( iter != end ) { - if ( *iter != this - && ! maximized - && ((*iter)->getFlags() & fc::shadow) != 0 ) + if ( *iter != this && ! maximized + && ((*iter)->getFlags() & fc::shadow) != 0 ) + { static_cast(*iter)->drawDialogShadow(); + } + ++iter; } } @@ -798,6 +860,7 @@ void FDialog::onWindowLowered (FEvent*) if ( ! window_list ) return; + if ( window_list->empty() ) return; @@ -807,8 +870,10 @@ void FDialog::onWindowLowered (FEvent*) while ( iter != end ) { putArea ((*iter)->getGlobalPos(), (*iter)->getVWin()); + if ( ! maximized && ((*iter)->getFlags() & fc::shadow) != 0 ) static_cast(*iter)->drawDialogShadow(); + ++iter; } } @@ -875,6 +940,7 @@ void FDialog::move (int x, int y) if ( x == xpos && y == ypos ) return; + if ( x+width < 1 || x > getColumnNumber() || y < 1 || y > getLineNumber() ) return; @@ -889,7 +955,6 @@ void FDialog::move (int x, int y) FWidget::move(x,y); xpos = x; ypos = y; - putArea (getGlobalPos(), vwin); if ( getGeometry().overlap(oldGeometry) ) @@ -941,11 +1006,14 @@ void FDialog::move (int x, int y) if ( overlaid ) { putArea ((*iter)->getGlobalPos(), (*iter)->getVWin()); + if ( ! maximized && ((*iter)->getFlags() & fc::shadow) != 0 ) static_cast(*iter)->drawDialogShadow(); } + if ( vwin == (*iter)->getVWin() ) overlaid = true; + ++iter; } } @@ -959,9 +1027,11 @@ void FDialog::move (int x, int y) { FPoint cursor_pos = FWidget::getFocusWidget()->getCursorPos(); cursor_pos -= FPoint(dx,dy); + if ( ! FWidget::getFocusWidget()->setCursorPos(cursor_pos) ) hideCursor(); } + updateTerminal(); } @@ -970,6 +1040,7 @@ void FDialog::setWidth (int w, bool adjust) { int old_width = width; FWidget::setWidth (w, adjust); + if ( vwin && width != old_width ) resizeArea (vwin); } @@ -979,6 +1050,7 @@ void FDialog::setHeight (int h, bool adjust) { int old_height = height; FWidget::setHeight (h, adjust); + if ( vwin && height != old_height ) resizeArea (vwin); } @@ -989,6 +1061,7 @@ void FDialog::setGeometry (int x, int y, int w, int h, bool adjust) int old_width = width; int old_height = height; FWidget::setGeometry (x, y, w, h, adjust); + if ( vwin && (width != old_width || height != old_height) ) resizeArea (vwin); } @@ -1014,6 +1087,7 @@ bool FDialog::setFocus (bool on) flags |= fc::focus; else flags &= ~fc::focus; + return on; } @@ -1033,6 +1107,7 @@ bool FDialog::setModal (bool on) flags &= ~fc::modal; modal_dialogs--; } + return on; } @@ -1055,6 +1130,7 @@ bool FDialog::setTransparentShadow (bool on) adjustWidgetSizeShadow = getGeometry() + getShadow(); adjustWidgetSizeGlobalShadow = getGeometryGlobal() + getShadow(); } + resizeArea (vwin); return on; } @@ -1081,6 +1157,7 @@ bool FDialog::setShadow (bool on) adjustWidgetSizeShadow = getGeometry() + getShadow(); adjustWidgetSizeGlobalShadow = getGeometryGlobal() + getShadow(); } + resizeArea (vwin); return on; } @@ -1092,6 +1169,7 @@ bool FDialog::setScrollable (bool on) flags |= fc::scrollable; else flags &= ~fc::scrollable; + return on; } @@ -1102,6 +1180,7 @@ bool FDialog::setResizeable (bool on) flags |= fc::resizeable; else flags &= ~fc::resizeable; + return on; } @@ -1112,6 +1191,7 @@ bool FDialog::setMaximized() return true; maximized = true; - // setGeometry(1, 1, xmax, ymax); + //setGeometry (1, 1, xmax, ymax); + return maximized; } diff --git a/src/fdialoglistmenu.cpp b/src/fdialoglistmenu.cpp index 7bdc860f..39f9e1d8 100644 --- a/src/fdialoglistmenu.cpp +++ b/src/fdialoglistmenu.cpp @@ -50,6 +50,7 @@ FDialogListMenu::~FDialogListMenu() void FDialogListMenu::init() { FMenuItem* menuitem = getItem(); + if ( menuitem ) menuitem->dialog_list = true; } diff --git a/src/ffiledialog.cpp b/src/ffiledialog.cpp index 18fdc250..5a399dba 100644 --- a/src/ffiledialog.cpp +++ b/src/ffiledialog.cpp @@ -61,6 +61,7 @@ FFileDialog::FFileDialog (const FFileDialog& fdlg) { if ( directory ) setPath(directory); + init(); } @@ -84,6 +85,7 @@ FFileDialog::FFileDialog ( const FString& dirname { if ( dirname ) setPath(dirname); + init(); } @@ -105,11 +107,14 @@ void FFileDialog::init() { int x, y; height = 15; - width = 42; + width = 42; + if ( width < 15 ) width = 15; + if ( width < 20 ) width = 20; + x = 1 + int((getParentWidget()->getWidth()-width)/2); y = 1 + int((getParentWidget()->getHeight()-height)/3); @@ -140,9 +145,9 @@ void FFileDialog::init() open = new FButton("&Save",this); else open = new FButton("&Open",this); + open->setGeometry(30, 10, 9, 1); open->setShadow(); - setGeometry (x, y, width, height); filename->addCallback @@ -150,34 +155,39 @@ void FFileDialog::init() "activate", _METHOD_CALLBACK (this, &FFileDialog::cb_processActivate) ); + filebrowser->addCallback ( "row-changed", _METHOD_CALLBACK (this, &FFileDialog::cb_processRowChanged) ); + filebrowser->addCallback ( "clicked", _METHOD_CALLBACK (this, &FFileDialog::cb_processClicked) ); + hidden->addCallback ( "toggled", _METHOD_CALLBACK (this, &FFileDialog::cb_processShowHidden) ); + cancel->addCallback ( "clicked", _METHOD_CALLBACK (this, &FFileDialog::cb_processCancel) ); + open->addCallback ( "clicked", _METHOD_CALLBACK (this, &FFileDialog::cb_processOpen) ); + setModal(); setTransparentShadow(); - readDir(); } @@ -205,6 +215,7 @@ inline bool FFileDialog::pattern_match ( const char* pattern , const char* fname ) { char search[128] = {}; + if ( show_hidden && fname[0] == '.' && fname[1] != '\0' ) // hidden files { search[0] = '.'; @@ -245,6 +256,7 @@ void FFileDialog::clear() int FFileDialog::numOfDirs() { int n = 0; + if ( ! dir_entries.empty() ) { std::vector::const_iterator iter, end; @@ -255,9 +267,11 @@ int FFileDialog::numOfDirs() { if ( (*iter).type == DT_DIR && strcmp((*iter).name, ".") != 0 ) n++; + ++iter; } } + return n; } @@ -296,7 +310,6 @@ int FFileDialog::changeDir (const FString& dirname) int i = 1; std::vector::const_iterator iter, end; const char* baseName = basename(const_cast(lastdir.c_str())); - iter = dir_entries.begin(); end = dir_entries.end(); @@ -308,6 +321,7 @@ int FFileDialog::changeDir (const FString& dirname) filename->setText(FString(baseName) + '/'); break; } + i++; ++iter; } @@ -316,11 +330,13 @@ int FFileDialog::changeDir (const FString& dirname) else { FString firstname = dir_entries[0].name; + if ( dir_entries[0].type == DT_DIR ) filename->setText(firstname + '/'); else filename->setText(firstname); } + printPath(directory); filename->redraw(); filebrowser->redraw(); @@ -367,11 +383,11 @@ void FFileDialog::cb_processActivate (FWidget*, void*) else { bool found = false; + if ( ! dir_entries.empty() ) { std::vector::const_iterator iter, end; FString input = filename->getText().trim(); - iter = dir_entries.begin(); end = dir_entries.end(); @@ -383,9 +399,11 @@ void FFileDialog::cb_processActivate (FWidget*, void*) changeDir(input); break; } + ++iter; } } + if ( ! found ) done (FDialog::Accept); } @@ -395,13 +413,17 @@ void FFileDialog::cb_processActivate (FWidget*, void*) void FFileDialog::cb_processRowChanged (FWidget*, void*) { int n = filebrowser->currentItem(); + if ( n == 0 ) return; + FString name = dir_entries[uLong(n-1)].name; + if ( dir_entries[uLong(n-1)].type == DT_DIR ) filename->setText( name + '/' ); else filename->setText( name ); + filename->redraw(); } @@ -443,10 +465,13 @@ void FFileDialog::adjustSize() int max_height = getRootWidget()->getClientHeight(); int max_width = getRootWidget()->getClientWidth(); int h = max_height - 6; + if ( h < 15 ) // minimum h = 15; + if ( h > 30 ) // maximum h = 30; + setHeight (h, false); X = 1 + int((max_width-width)/2); Y = 1 + int((max_height-height)/3); @@ -475,9 +500,7 @@ FFileDialog& FFileDialog::operator = (const FFileDialog& fdlg) delete filebrowser; delete filename; clear(); - fdlg.getParentWidget()->addChild (this); - directory = fdlg.directory; filter_pattern = fdlg.filter_pattern; dlg_type = fdlg.dlg_type; @@ -485,8 +508,8 @@ FFileDialog& FFileDialog::operator = (const FFileDialog& fdlg) if ( directory ) setPath(directory); - init(); + init(); return *this; } } @@ -530,6 +553,7 @@ void FFileDialog::setPath (const FString& dir) directory = '/'; return; } + if ( S_ISLNK(sb.st_mode) ) { if ( lstat(dirname, &sb) != 0 ) @@ -538,6 +562,7 @@ void FFileDialog::setPath (const FString& dir) return; } } + if ( ! S_ISDIR(sb.st_mode) ) { directory = '/'; @@ -575,10 +600,12 @@ const FString FFileDialog::getSelectedFile() const //---------------------------------------------------------------------- int FFileDialog::readDir() { + int start, dir_num; const char* dir = directory.c_str(); const char* filter = filter_pattern.c_str(); errno = 0; directory_stream = opendir(dir); + if ( ! directory_stream ) { FMessageBox::error (this, "Can't open directory\n" + directory); @@ -591,17 +618,23 @@ int FFileDialog::readDir() { errno = 0; struct dirent* next = readdir (directory_stream); + if ( next ) { if ( next->d_name[0] == '.' && next->d_name[1] == '\0' ) continue; + if ( ! show_hidden && next->d_name[0] == '.' && next->d_name[1] != '\0' && next->d_name[1] != '.' ) + { continue; + } + if ( dir[0] == '/' && dir[1] == '\0' && strcmp(next->d_name, "..") == 0 ) continue; + dir_entry entry; entry.name = strdup(next->d_name); entry.type = next->d_type; @@ -616,6 +649,7 @@ int FFileDialog::readDir() if ( realpath(symLink, resolved_path) != 0 ) // follow link { struct stat sb; + if ( lstat(resolved_path, &sb) == 0 ) { if ( S_ISDIR(sb.st_mode) ) @@ -623,6 +657,7 @@ int FFileDialog::readDir() } } } + if ( entry.type == DT_DIR ) dir_entries.push_back (entry); else if ( pattern_match(filter, entry.name) ) @@ -633,11 +668,13 @@ int FFileDialog::readDir() else if (errno != 0) { FMessageBox::error (this, "Reading directory\n" + directory); + if ( errno != EOVERFLOW ) break; } else break; + } // end while if ( closedir (directory_stream) != 0 ) @@ -646,24 +683,21 @@ int FFileDialog::readDir() return -2; } - int start; if ( strcmp((*dir_entries.begin()).name, "..") == 0 ) start=1; else start=0; - int dir_num = numOfDirs(); + dir_num = numOfDirs(); // directories first std::sort(dir_entries.begin()+start, dir_entries.end(), sortDirFirst); - // sort directories by name std::sort(dir_entries.begin()+start, dir_entries.begin()+dir_num, sortByName); - // sort files by name std::sort(dir_entries.begin()+dir_num, dir_entries.end(), sortByName); - // fill list with directory entries filebrowser->clear(); + if ( ! dir_entries.empty() ) { std::vector::const_iterator iter, end; @@ -676,9 +710,11 @@ int FFileDialog::readDir() filebrowser->insert(FString((*iter).name), fc::SquareBrackets); else filebrowser->insert(FString((*iter).name)); + ++iter; } } + return 0; } @@ -699,17 +735,22 @@ FString FFileDialog::fileOpenChooser ( FWidget* parent , const FString& dirname , const FString& filter ) { + FFileDialog* fileopen; FString ret; FString path = dirname; FString file_filter = filter; + if ( path.isNull() ) path = getHomeDir(); + if ( file_filter.isNull() ) file_filter = FString("*"); - FFileDialog* fileopen = new FFileDialog ( path - , file_filter - , FFileDialog::Open - , parent ); + + fileopen = new FFileDialog ( path + , file_filter + , FFileDialog::Open + , parent ); + if ( fileopen->exec() == FDialog::Accept ) ret = fileopen->getPath() + fileopen->getSelectedFile(); else @@ -724,21 +765,27 @@ FString FFileDialog::fileSaveChooser ( FWidget* parent , const FString& dirname , const FString& filter ) { + FFileDialog* fileopen; FString ret; FString path = dirname; FString file_filter = filter; + if ( path.isNull() ) path = getHomeDir(); + if ( file_filter.isNull() ) file_filter = FString("*"); - FFileDialog* fileopen = new FFileDialog ( path - , file_filter - , FFileDialog::Save - , parent ); + + fileopen = new FFileDialog ( path + , file_filter + , FFileDialog::Save + , parent ); + if ( fileopen->exec() == FDialog::Accept ) ret = fileopen->getPath() + fileopen->getSelectedFile(); else ret = FString(); + delete fileopen; return ret; } diff --git a/src/flabel.cpp b/src/flabel.cpp index c1171dee..f26c4a35 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -59,7 +59,6 @@ void FLabel::init() flags |= fc::active; unsetFocusable(); - foregroundColor = getParentWidget()->getForegroundColor(); backgroundColor = getParentWidget()->getBackgroundColor(); } @@ -86,6 +85,7 @@ uChar FLabel::getHotkey() return 0;; } } + return 0; } @@ -105,8 +105,10 @@ int FLabel::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) i++; src++; } + *dest++ = *src++; } + return hotkeypos; } @@ -114,6 +116,7 @@ int FLabel::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) void FLabel::setHotkeyAccelerator() { int hotkey = getHotkey(); + if ( hotkey ) { if ( isalpha(hotkey) || isdigit(hotkey) ) @@ -163,7 +166,6 @@ void FLabel::printLine ( wchar_t*& line { int to_char; bool isActive, isNoUnderline; - isActive = ((flags & fc::active) != 0); isNoUnderline = ((flags & fc::no_underline) != 0); @@ -191,11 +193,15 @@ void FLabel::printLine ( wchar_t*& line if ( (z == hotkeypos) && isActive ) { setColor (wc.label_hotkey_fg, wc.label_hotkey_bg); + if ( ! isNoUnderline ) setUnderline(); + print ( line[z] ); + if ( ! isNoUnderline ) unsetUnderline(); + if ( hasEmphasis() ) setColor (emphasis_color, backgroundColor); else @@ -281,6 +287,7 @@ void FLabel::draw() xoffset = getXOffset (int(length)); printLine (LabelText, length, -1, xoffset); } + y++; delete[] LabelText; } @@ -291,7 +298,6 @@ void FLabel::draw() LabelText = new wchar_t[length+1](); src = const_cast(text.wc_str()); dest = const_cast(LabelText); - hotkeypos = getHotkeyPos (src, dest, length); if ( hotkeypos != -1 ) @@ -302,12 +308,15 @@ void FLabel::draw() printLine (LabelText, length, hotkeypos, xoffset); delete[] LabelText; } + if ( isMonochron() ) { setReverse(false); + if ( hasEmphasis() ) setBold(false); } + setUpdateVTerm(true); } @@ -320,11 +329,9 @@ void FLabel::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); - blank = new char[width+1]; memset(blank, ' ', uLong(width)); blank[width] = '\0'; @@ -347,9 +354,12 @@ void FLabel::onMouseDown (FMouseEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); accel_widget->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + accel_widget->redraw(); + if ( statusBar() ) { accel_widget->statusBar()->drawMessage(); @@ -371,9 +381,12 @@ void FLabel::onAccel (FAccelEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); accel_widget->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + accel_widget->redraw(); + if ( statusBar() ) { accel_widget->statusBar()->drawMessage(); @@ -381,6 +394,7 @@ void FLabel::onAccel (FAccelEvent* ev) flush_out(); } } + ev->accept(); } @@ -420,6 +434,7 @@ bool FLabel::setEmphasis (bool on) { if ( emphasis != on ) emphasis = on; + return on; } @@ -428,6 +443,7 @@ bool FLabel::setReverseMode (bool on) { if ( reverse_mode != on ) reverse_mode = on; + return on; } @@ -446,6 +462,7 @@ bool FLabel::setEnable (bool on) flags &= ~fc::active; delAccelerator(); } + return on; } @@ -460,6 +477,7 @@ void FLabel::setText (const FString& txt) { text = txt; multiline_text = text.split("\r\n"); + if ( int(multiline_text.size()) > 1 ) multiline = true; else diff --git a/src/flineedit.cpp b/src/flineedit.cpp index 5975ac71..88633292 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -54,9 +54,11 @@ FLineEdit::~FLineEdit() // destructor setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); setConsoleCursor(fc::underscore_cursor); + if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } + if ( hasFocus() ) hideCursor(); } @@ -98,6 +100,7 @@ bool FLineEdit::hasHotkey() { if ( label_text.isEmpty() ) return 0; + return label_text.includes('&'); } @@ -105,14 +108,14 @@ bool FLineEdit::hasHotkey() void FLineEdit::draw() { bool isFocus; - drawInputField(); - isFocus = ((flags & fc::focus) != 0); + if ( isFocus && statusBar() ) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) { statusBar()->setMessage(msg); @@ -134,10 +137,12 @@ void FLineEdit::drawInputField() setUpdateVTerm(false); gotoxy (xpos+xmin-1, ypos+ymin-1); + if ( isMonochron() ) { setReverse(true); print (' '); + if ( isActiveFocus ) setReverse(false); else @@ -146,6 +151,7 @@ void FLineEdit::drawInputField() else if ( isActiveFocus ) { setColor (wc.inputfield_active_focus_bg, wc.dialog_bg); + if ( isCygwinTerminal() ) // IBM Codepage 850 print (fc::FullBlock); // █ else if ( isTeraTerm() ) @@ -156,6 +162,7 @@ void FLineEdit::drawInputField() else if ( isActive ) { setColor (wc.inputfield_active_bg, wc.dialog_bg); + if ( isCygwinTerminal() ) // IBM Codepage 850 print (fc::FullBlock); // █ else if ( isTeraTerm() ) @@ -166,6 +173,7 @@ void FLineEdit::drawInputField() else // isInactive { setColor (wc.inputfield_inactive_bg, wc.dialog_bg); + if ( isCygwinTerminal() ) // IBM Codepage 850 print (fc::FullBlock); // █ else if ( isTeraTerm() ) @@ -183,14 +191,17 @@ void FLineEdit::drawInputField() if ( isUTF8_linux_terminal() ) { setUTF8(true); + if ( show_text ) print (show_text); + setUTF8(false); } else if ( show_text ) print (show_text); x = int(show_text.getLength()); + while ( x < width-1 ) { print (' '); @@ -228,6 +239,7 @@ void FLineEdit::processActivate() setFocus(); redraw(); } + emitCallback("activate"); } @@ -279,7 +291,6 @@ void FLineEdit::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); @@ -294,8 +305,8 @@ void FLineEdit::hide() gotoxy (xpos+xmin-1, ypos+ymin-1+y); print (blank); } - delete[] blank; + delete[] blank; lable_Length = int(label_text.getLength()); if ( lable_Length > 0 ) @@ -313,6 +324,7 @@ void FLineEdit::hide() gotoxy (xpos+xmin-int(lable_Length)-1, ypos+ymin-1); break; } + blank = new char[lable_Length+1]; memset(blank, ' ', uLong(size)); blank[lable_Length] = '\0'; @@ -329,6 +341,7 @@ bool FLineEdit::setEnable (bool on) if ( on ) { flags |= fc::active; + if ( hasFocus() ) { foregroundColor = wc.inputfield_active_focus_fg; @@ -346,6 +359,7 @@ bool FLineEdit::setEnable (bool on) foregroundColor = wc.inputfield_inactive_fg; backgroundColor = wc.inputfield_inactive_bg; } + return on; } @@ -367,6 +381,7 @@ bool FLineEdit::setFocus (bool on) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) statusBar()->setMessage(msg); } @@ -380,10 +395,12 @@ bool FLineEdit::setFocus (bool on) { foregroundColor = wc.inputfield_active_fg; backgroundColor = wc.inputfield_active_bg; + if ( statusBar() ) statusBar()->clearMessage(); } } + return on; } @@ -396,6 +413,7 @@ bool FLineEdit::setShadow (bool on) flags |= fc::shadow; else flags &= ~fc::shadow; + return on; } @@ -409,19 +427,25 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) { case fc::Fkey_left: cursor_pos--; + if ( cursor_pos < 0 ) cursor_pos=0; + if ( cursor_pos < offset ) offset--; + ev->accept(); break; case fc::Fkey_right: cursor_pos++; + if ( cursor_pos >= len ) cursor_pos=len; + if ( cursor_pos-offset >= width-2 && offset <= len-width+1 ) offset++; + ev->accept(); break; @@ -444,12 +468,16 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) text.remove(uInt(cursor_pos), 1); processChanged(); } + if ( cursor_pos >= len ) cursor_pos=len; + if ( cursor_pos < 0 ) cursor_pos=0; + if ( offset > 0 && len-offset < width-1 ) offset--; + ev->accept(); break; @@ -460,19 +488,23 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) text.remove(uInt(cursor_pos-1), 1); processChanged(); cursor_pos--; + if ( offset > 0 ) offset--; } + ev->accept(); break; case fc::Fkey_ic: // insert key insert_mode = not insert_mode; + if ( insert_mode ) { setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); setConsoleCursor(fc::underscore_cursor); + if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } @@ -481,9 +513,11 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) setXTermCursorStyle(fc::steady_block); setKDECursor(fc::BlockCursor); setConsoleCursor(fc::full_block_cursor); + if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:eeee/0000/0000"); } + ev->accept(); break; @@ -511,6 +545,7 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) text.insert(wchar_t(key), uInt(cursor_pos)); else text.overwrite(wchar_t(key), uInt(cursor_pos)); + processChanged(); } else @@ -519,8 +554,10 @@ void FLineEdit::onKeyPress (FKeyEvent* ev) processChanged(); } cursor_pos++; + if ( cursor_pos >= width-1 ) offset++; + ev->accept(); } else @@ -551,9 +588,12 @@ void FLineEdit::onMouseDown (FMouseEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + redraw(); + if ( statusBar() ) statusBar()->drawMessage(); } @@ -565,8 +605,10 @@ void FLineEdit::onMouseDown (FMouseEvent* ev) { int len = int(text.getLength()); cursor_pos = offset + mouse_x - 2; + if ( cursor_pos >= len ) cursor_pos = len; + drawInputField(); updateTerminal(); } @@ -597,10 +639,11 @@ void FLineEdit::onMouseMove (FMouseEvent* ev) if ( mouse_x >= 2 && mouse_x <= width && mouse_y == 1 ) { - cursor_pos = offset + mouse_x - 2; + if ( cursor_pos >= len ) cursor_pos=len; + drawInputField(); updateTerminal(); } @@ -615,6 +658,7 @@ void FLineEdit::onMouseMove (FMouseEvent* ev) addTimer(scrollRepeat); dragScroll = FLineEdit::scrollLeft; } + if ( offset == 0 ) { delOwnTimer(); @@ -630,6 +674,7 @@ void FLineEdit::onMouseMove (FMouseEvent* ev) addTimer(scrollRepeat); dragScroll = FLineEdit::scrollRight; } + if ( offset == len-width+2 ) { delOwnTimer(); @@ -656,18 +701,22 @@ void FLineEdit::onTimer (FTimerEvent*) return; case FLineEdit::scrollLeft: - if ( offset == 0) { dragScroll = FLineEdit::noScroll; return; } + offset--; + if ( offset < 0 ) offset = 0; + cursor_pos--; + if ( cursor_pos < 0 ) cursor_pos = 0; + break; case FLineEdit::scrollRight: @@ -676,10 +725,14 @@ void FLineEdit::onTimer (FTimerEvent*) dragScroll = FLineEdit::noScroll; return; } + offset++; + if ( offset > len-width+2 ) offset = len-width+2; + cursor_pos++; + if ( cursor_pos > len ) cursor_pos = len; @@ -702,9 +755,12 @@ void FLineEdit::onAccel (FAccelEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + redraw(); + if ( statusBar() ) { statusBar()->drawMessage(); @@ -712,6 +768,7 @@ void FLineEdit::onAccel (FAccelEvent* ev) flush_out(); } } + ev->accept(); } } @@ -727,6 +784,7 @@ void FLineEdit::onHide (FHideEvent*) if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } + if ( hasFocus() ) hideCursor(); } @@ -753,6 +811,7 @@ void FLineEdit::onFocusIn (FFocusEvent*) if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:0000/0000/0000"); } + if ( statusBar() ) { statusBar()->drawMessage(); @@ -775,6 +834,7 @@ void FLineEdit::onFocusOut (FFocusEvent*) setXTermCursorStyle(fc::blinking_underline); setKDECursor(fc::UnderlineCursor); setConsoleCursor(fc::underscore_cursor); + if ( isUrxvtTerminal() ) setXTermCursorColor("rgb:ffff/ffff/ffff"); } @@ -795,6 +855,7 @@ void FLineEdit::setText (FString txt) { offset = 0; cursor_pos = 0; + if ( txt ) text = txt; else diff --git a/src/flistbox.cpp b/src/flistbox.cpp index f167a8a9..1e562b95 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -92,6 +92,7 @@ void FListBox::init() { if ( hasFocus() ) flags = fc::focus; + if ( isEnabled() ) flags |= fc::active; @@ -117,6 +118,7 @@ void FListBox::init() "change-value", _METHOD_CALLBACK (this, &FListBox::cb_VBarChange) ); + HBar->addCallback ( "change-value", @@ -134,17 +136,23 @@ void FListBox::draw() setUpdateVTerm(false); setColor (foregroundColor, backgroundColor); + if ( isMonochron() ) setReverse(true); + if ( isNewFont() ) width--; + drawBorder(); + if ( isNewFont() ) { width++; + if ( ! VBar->isVisible() ) { setColor (foregroundColor, backgroundColor); + for (int y=ypos+ymin; y < ypos+ymin+height-2; y++) { gotoxy(xpos+xmin+width-2, y); @@ -152,24 +160,28 @@ void FListBox::draw() } } } + drawLabel(); + if ( isMonochron() ) setReverse(false); + setUpdateVTerm(true); if ( VBar->isVisible() ) VBar->redraw(); + if ( HBar->isVisible() ) HBar->redraw(); drawList(); - isFocus = ((flags & fc::focus) != 0); if ( isFocus && statusBar() ) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) { statusBar()->setMessage(msg); @@ -195,6 +207,7 @@ void FListBox::drawLabel() setColor(wc.label_emphasis_fg, wc.label_bg); else setColor(wc.label_inactive_fg, wc.label_inactive_bg); + if ( length <= uInt(width-2) ) print (txt); else @@ -235,6 +248,7 @@ void FListBox::drawList() } setUpdateVTerm(false); + for (uInt y=start; y < end; y++) { gotoxy (xpos+xmin, ypos+ymin+int(y)); @@ -262,6 +276,7 @@ void FListBox::drawList() { if ( isFocus && getMaxColor() < 16 ) setBold(); + if ( isLineSelected ) { if ( isMonochron() ) @@ -272,6 +287,7 @@ void FListBox::drawList() else setColor ( wc.selected_current_element_fg , wc.selected_current_element_bg ); + setCursorPos ( xpos+xmin+1 , ypos+ymin+int(y) ); // first character } @@ -279,10 +295,12 @@ void FListBox::drawList() { if ( isMonochron() ) unsetBold(); + if ( isFocus ) { setColor ( wc.current_element_focus_fg , wc.current_element_focus_bg ); + if ( inc_len > 0 ) { serach_mark = true; @@ -298,6 +316,7 @@ void FListBox::drawList() setColor ( wc.current_element_fg , wc.current_element_bg ); } + if ( isMonochron() ) setReverse(false); } @@ -314,6 +333,7 @@ void FListBox::drawList() print ('>'); else print (' '); + if ( lineHasBrackets ) { const wchar_t* element_str; @@ -325,23 +345,29 @@ void FListBox::drawList() if ( xoffset == 0 ) { b=1; + switch ( data[y+uInt(yoffset)].brackets ) { case fc::NoBrackets: break; + case fc::SquareBrackets: print ('['); break; + case fc::Parenthesis: print ('('); break; + case fc::CurlyBrackets: print ('{'); break; + case fc::AngleBrackets: print ('<'); break; } + element = data[y+uInt(yoffset)].getText() .mid ( uInt(1+xoffset) , uInt(width-nf_offset-5) ); @@ -350,6 +376,7 @@ void FListBox::drawList() element = data[y+uInt(yoffset)].getText() .mid ( uInt(xoffset) , uInt(width-nf_offset-4) ); + element_str = element.wc_str(); len = element.getLength(); @@ -358,41 +385,53 @@ void FListBox::drawList() if ( serach_mark && i == 0 ) setColor ( wc.current_inc_search_element_fg , wc.current_element_focus_bg ); + if ( serach_mark && i == inc_len ) setColor ( wc.current_element_focus_fg , wc.current_element_focus_bg ); + print (element_str[i]); } + full_length = int(data[y+uInt(yoffset)].getText().getLength()); + if ( b+i < uInt(width-nf_offset-4) && xoffset <= full_length+1 ) { if ( serach_mark && i == inc_len ) setColor ( wc.current_element_focus_fg , wc.current_element_focus_bg ); + switch ( data[y+uInt(yoffset)].brackets ) { case fc::NoBrackets: break; + case fc::SquareBrackets: print (']'); break; + case fc::Parenthesis: print (')'); break; + case fc::CurlyBrackets: print ('}'); break; + case fc::AngleBrackets: print ('>'); break; } + i++; } + if ( isMonochron() && isCurrentLine ) { print ('<'); i++; } + for (; b+i < uInt(width-nf_offset-3); i++) print (' '); } @@ -409,6 +448,7 @@ void FListBox::drawList() if ( serach_mark ) setColor ( wc.current_inc_search_element_fg , wc.current_element_focus_bg ); + for (i=0; i < len; i++) { if ( serach_mark && i == inc_len ) @@ -417,11 +457,13 @@ void FListBox::drawList() print (element_str[i]); } + if ( isMonochron() && isCurrentLine ) { print ('<'); i++; } + for (; i < uInt(width-nf_offset-3); i++) print (' '); } @@ -465,12 +507,16 @@ void FListBox::processChanged() void FListBox::adjustYOffset() { int element_count = int(count()); + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; + if ( yoffset < 0 ) yoffset = 0; + if ( current < yoffset ) current = yoffset; + if ( current >= yoffset + height - 1 ) yoffset = current - height + 2; } @@ -480,7 +526,6 @@ void FListBox::adjustSize() { int element_count; adjustYOffset(); - FWidget::adjustSize(); element_count = int(count()); @@ -512,21 +557,24 @@ void FListBox::adjustSize() void FListBox::setCurrentItem(int index) { int element_count; + if ( index == current ) return; element_count = int(count()); + if ( index > element_count ) current = element_count; else if ( index < 1 ) current = 1; else current = index; + xoffset = 0; yoffset = 0; adjustSize(); - VBar->setValue(yoffset); + if ( isVisible() ) redraw(); } @@ -539,21 +587,21 @@ void FListBox::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); - n = isNewFont() ? 1 : 0; size = width + n; blank = new char[size+1]; memset(blank, ' ', uLong(size)); blank[size] = '\0'; + for (int y=0; y < height; y++) { gotoxy (xpos+xmin-1, ypos+ymin-1+y); print (blank); } + delete[] blank; } @@ -570,11 +618,13 @@ void FListBox::showInsideBrackets ( int index if ( len > maxLineWidth ) { maxLineWidth = len; + if ( len >= width - nf_offset - 3 ) { HBar->setMaximum(maxLineWidth - width + nf_offset + 4); HBar->setPageSize(maxLineWidth, width - nf_offset - 4); HBar->setValue (xoffset); + if ( ! HBar->isVisible() ) HBar->setVisible(); } @@ -586,6 +636,7 @@ void FListBox::showInsideBrackets ( int index void FListBox::setGeometry (int x, int y, int w, int h, bool adjust) { FWidget::setGeometry(x, y, w, h, adjust); + if ( isNewFont() ) { VBar->setGeometry(width, 2, 2, height-2); @@ -607,6 +658,7 @@ bool FListBox::setEnable (bool on) flags |= fc::active; else flags &= ~fc::active; + return on; } @@ -623,6 +675,7 @@ bool FListBox::setFocus (bool on) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) statusBar()->setMessage(msg); } @@ -634,6 +687,7 @@ bool FListBox::setFocus (bool on) if ( statusBar() ) statusBar()->clearMessage(); } + return on; } @@ -644,6 +698,7 @@ bool FListBox::setShadow (bool on) flags |= fc::shadow; else flags &= ~fc::shadow; + return on; } @@ -667,66 +722,85 @@ void FListBox::onKeyPress (FKeyEvent* ev) case fc::Fkey_up: current--; + if ( current < 1 ) current=1; + if ( current <= yoffset ) yoffset--; + inc_search.clear(); ev->accept(); break; case fc::Fkey_down: current++; + if ( current > element_count ) current = element_count; + if ( current - yoffset >= height - 1 ) yoffset++; + inc_search.clear(); ev->accept(); break; case fc::Fkey_left: xoffset--; + if ( xoffset < 0 ) xoffset = 0; + inc_search.clear(); ev->accept(); break; case fc::Fkey_right: xoffset++; + if ( xoffset > maxLineWidth - width + nf_offset + 4 ) xoffset = maxLineWidth - width + nf_offset + 4; + if ( xoffset < 0 ) xoffset = 0; + inc_search.clear(); ev->accept(); break; case fc::Fkey_ppage: current -= height-3; + if ( current < 1 ) current=1; + if ( current <= yoffset ) { yoffset -= height-3; + if ( yoffset < 0 ) yoffset=0; } + inc_search.clear(); ev->accept(); break; case fc::Fkey_npage: current += height-3; + if ( current > element_count ) current = element_count; + if ( current - yoffset >= height - 1 ) { yoffset += height-3; + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; } + inc_search.clear(); ev->accept(); break; @@ -740,8 +814,10 @@ void FListBox::onKeyPress (FKeyEvent* ev) case fc::Fkey_end: current = element_count; + if ( current >= height - 1 ) yoffset = element_count - height + 2; + inc_search.clear(); ev->accept(); break; @@ -753,25 +829,32 @@ void FListBox::onKeyPress (FKeyEvent* ev) unselectItem(current); else selectItem(current); + processSelect(); current++; + if ( current > element_count ) current = element_count; + if ( current-yoffset >= height - 1 ) yoffset++; + ev->accept(); } + inc_search.clear(); break; case fc::Fkey_space: { uInt inc_len = inc_search.getLength(); + if ( inc_len > 0 ) { inc_search += L' '; bool inc_found = false; uInt end = count(); + for (uInt i=0; i < end; i++) { if ( ! inc_found @@ -783,6 +866,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) break; } } + if ( ! inc_found ) { inc_search.remove(inc_len, 1); @@ -797,6 +881,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) unselectItem(current); else selectItem(current); + processSelect(); inc_search.clear(); ev->accept(); @@ -808,6 +893,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) case fc::Fkey_backspace: { uInt inc_len = inc_search.getLength(); + if ( inc_len > 0 ) { inc_search.remove(inc_len-1, 1); @@ -815,6 +901,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) if ( inc_len > 1 ) { uInt end = count(); + for (uInt i=0; i < end; i++) { if ( inc_search.toLower() @@ -825,6 +912,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) } } } + ev->accept(); } else @@ -849,9 +937,11 @@ void FListBox::onKeyPress (FKeyEvent* ev) inc_search = wchar_t(key); else inc_search += wchar_t(key); + uInt inc_len = inc_search.getLength(); bool inc_found = false; uInt end = count(); + for (uInt i=0; i < end; i++) { if ( ! inc_found @@ -863,9 +953,11 @@ void FListBox::onKeyPress (FKeyEvent* ev) break; } } + if ( ! inc_found ) { inc_search.remove(inc_len-1, 1); + if ( inc_len == 1 ) ev->ignore(); else @@ -881,6 +973,7 @@ void FListBox::onKeyPress (FKeyEvent* ev) if ( current_before != current ) { processChanged(); + if ( ! isMultiSelection() ) processSelect(); } @@ -889,10 +982,14 @@ void FListBox::onKeyPress (FKeyEvent* ev) { if ( isVisible() ) drawList(); + VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + HBar->setValue (xoffset); + if ( HBar->isVisible() && xoffset_before != xoffset ) HBar->drawBar(); @@ -911,6 +1008,7 @@ void FListBox::onMouseDown (FMouseEvent* ev) { return; } + if ( ev->getButton() == fc::RightButton && ! isMultiSelection() ) return; @@ -929,13 +1027,16 @@ void FListBox::onMouseDown (FMouseEvent* ev) yoffset_before = yoffset; mouse_x = ev->getX(); mouse_y = ev->getY(); + if ( mouse_x > 1 && mouse_x < width && mouse_y > 1 && mouse_y < height ) { current = yoffset + mouse_y - 1; + if ( current > int(count()) ) current = int(count()); inc_search.clear(); + if ( ev->getButton() == fc::RightButton ) { if ( isMultiSelection() ) @@ -950,16 +1051,20 @@ void FListBox::onMouseDown (FMouseEvent* ev) mouseSelect = true; selectItem(current); } + processSelect(); secect_from_item = current; } } + if ( isVisible() ) drawList(); VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); flush_out(); } @@ -980,10 +1085,12 @@ void FListBox::onMouseUp (FMouseEvent* ev) { int mouse_x = ev->getX(); int mouse_y = ev->getY(); + if ( mouse_x > 1 && mouse_x < width && mouse_y > 1 && mouse_y < height ) { processChanged(); + if ( ! isMultiSelection() ) processSelect(); } @@ -1000,6 +1107,7 @@ void FListBox::onMouseMove (FMouseEvent* ev) { return; } + if ( ev->getButton() == fc::RightButton && ! isMultiSelection() ) return; @@ -1012,8 +1120,10 @@ void FListBox::onMouseMove (FMouseEvent* ev) && mouse_y > 1 && mouse_y < height ) { current = yoffset + mouse_y - 1; + if ( current > int(count()) ) current = int(count()); + inc_search.clear(); // handle multiple selections @@ -1046,14 +1156,18 @@ void FListBox::onMouseMove (FMouseEvent* ev) processSelect(); } } + secect_from_item = current; } if ( isVisible() ) drawList(); + VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); flush_out(); } @@ -1064,15 +1178,18 @@ void FListBox::onMouseMove (FMouseEvent* ev) // drag up if ( dragScroll != FListBox::noScroll && scrollDistance < height-2 ) scrollDistance++; + if ( ! scrollTimer && current > 1 ) { scrollTimer = true; addTimer(scrollRepeat); + if ( ev->getButton() == fc::RightButton ) dragScroll = FListBox::scrollUpSelect; else dragScroll = FListBox::scrollUp; } + if ( current == 1 ) { delOwnTimer(); @@ -1084,15 +1201,18 @@ void FListBox::onMouseMove (FMouseEvent* ev) // drag down if ( dragScroll != FListBox::noScroll && scrollDistance < height-2 ) scrollDistance++; + if ( ! scrollTimer && current < int(count()) ) { scrollTimer = true; addTimer(scrollRepeat); + if ( ev->getButton() == fc::RightButton ) dragScroll = FListBox::scrollDownSelect; else dragScroll = FListBox::scrollDown; } + if ( current == int(count()) ) { delOwnTimer(); @@ -1125,6 +1245,7 @@ void FListBox::onMouseDoubleClick (FMouseEvent* ev) { if ( yoffset + mouse_y - 1 > int(count()) ) return; + processClick(); } } @@ -1148,11 +1269,15 @@ void FListBox::onTimer (FTimerEvent*) dragScroll = FListBox::noScroll; return; } + current -= scrollDistance; + if ( current < 1 ) current=1; + if ( current <= yoffset ) yoffset -= scrollDistance; + if ( yoffset < 0 ) yoffset=0; break; @@ -1164,11 +1289,15 @@ void FListBox::onTimer (FTimerEvent*) dragScroll = FListBox::noScroll; return; } + current += scrollDistance; + if ( current > element_count ) current = element_count; + if ( current - yoffset >= height - 1 ) yoffset += scrollDistance; + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; @@ -1194,6 +1323,7 @@ void FListBox::onTimer (FTimerEvent*) from = secect_from_item + 1; to = current; } + for (int i=from; i <= to; i++) { if ( mouseSelect ) @@ -1207,15 +1337,19 @@ void FListBox::onTimer (FTimerEvent*) processSelect(); } } + secect_from_item = current; } } if ( isVisible() ) drawList(); + VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); flush_out(); } @@ -1224,7 +1358,6 @@ void FListBox::onTimer (FTimerEvent*) void FListBox::onWheel (FWheelEvent* ev) { int element_count, current_before, yoffset_before, yoffset_end, wheel; - element_count = int(count()); current_before = current; yoffset_before = yoffset; @@ -1248,7 +1381,9 @@ void FListBox::onWheel (FWheelEvent* ev) case fc::WheelUp: if ( yoffset == 0 ) break; + yoffset -= 4; + if ( yoffset < 0 ) { current -= 4+yoffset; @@ -1256,15 +1391,19 @@ void FListBox::onWheel (FWheelEvent* ev) } else current -= 4; + if ( current < 1 ) current=1; + inc_search.clear(); break; case fc::WheelDown: if ( yoffset == yoffset_end ) break; + yoffset += 4; + if ( yoffset > yoffset_end ) { current += 4 - (yoffset - yoffset_end); @@ -1272,8 +1411,10 @@ void FListBox::onWheel (FWheelEvent* ev) } else current += 4; + if ( current > element_count ) current = element_count; + inc_search.clear(); break; @@ -1284,6 +1425,7 @@ void FListBox::onWheel (FWheelEvent* ev) if ( current_before != current ) { processChanged(); + if ( ! isMultiSelection() ) processSelect(); } @@ -1292,8 +1434,10 @@ void FListBox::onWheel (FWheelEvent* ev) drawList(); VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); flush_out(); } @@ -1303,6 +1447,7 @@ void FListBox::onFocusIn (FFocusEvent*) { if ( statusBar() ) statusBar()->drawMessage(); + inc_search.clear(); } @@ -1314,6 +1459,7 @@ void FListBox::onFocusOut (FFocusEvent*) statusBar()->clearMessage(); statusBar()->drawMessage(); } + delOwnTimer(); inc_search.clear(); } @@ -1333,12 +1479,16 @@ void FListBox::cb_VBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepBackward: current -= distance; + if ( current < 1 ) current=1; + if ( current <= yoffset ) yoffset -= distance; + if ( yoffset < 0 ) yoffset = 0; + break; case FScrollbar::scrollPageForward: @@ -1346,30 +1496,42 @@ void FListBox::cb_VBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepForward: current += distance; + if ( current > element_count ) current = element_count; + if ( current - yoffset >= height - 1 ) yoffset += distance; + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; + break; case FScrollbar::scrollJump: { int val = VBar->getValue(); + if ( yoffset == val ) break; + int c = current - yoffset; yoffset = val; + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; + if ( yoffset < 0 ) yoffset = 0; + current = yoffset + c; + if ( current < yoffset ) current = yoffset; + if ( current > element_count ) current = element_count; + break; } @@ -1398,8 +1560,10 @@ void FListBox::cb_VBarChange (FWidget*, void*) && scrollType <= FScrollbar::scrollPageForward ) { VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); flush_out(); } @@ -1420,6 +1584,7 @@ void FListBox::cb_HBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepBackward: xoffset -= distance; + if ( xoffset < 0 ) xoffset = 0; break; @@ -1429,39 +1594,53 @@ void FListBox::cb_HBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepForward: xoffset += distance; + if ( xoffset > maxLineWidth - width + nf_offset + 4 ) xoffset = maxLineWidth - width + nf_offset + 4; + if ( xoffset < 0 ) xoffset = 0; + break; case FScrollbar::scrollJump: { int val = HBar->getValue(); + if ( xoffset == val ) break; + xoffset = val; + if ( xoffset > maxLineWidth - width + nf_offset + 4 ) xoffset = maxLineWidth - width + nf_offset + 4; + if ( xoffset < 0 ) xoffset = 0; + break; } case FScrollbar::scrollWheelUp: if ( xoffset == 0 ) break; + xoffset -= 4; + if ( xoffset < 0 ) xoffset=0; + break; case FScrollbar::scrollWheelDown: if ( xoffset == xoffset_end ) break; + xoffset += 4; + if ( xoffset > xoffset_end ) xoffset = xoffset_end; + break; default: @@ -1479,8 +1658,10 @@ void FListBox::cb_HBarChange (FWidget*, void*) && scrollType <= FScrollbar::scrollWheelDown ) { HBar->setValue (xoffset); + if ( HBar->isVisible() && xoffset_before != xoffset ) HBar->drawBar(); + updateTerminal(); flush_out(); } @@ -1494,17 +1675,20 @@ void FListBox::insert ( FString item int len, element_count; len = int(item.getLength()); + if ( b ) len += 2; if ( len > maxLineWidth ) { maxLineWidth = len; + if ( len >= width - nf_offset - 3 ) { HBar->setMaximum(maxLineWidth - width + nf_offset + 4); HBar->setPageSize(maxLineWidth, width - nf_offset - 4); HBar->calculateSliderValues(); + if ( ! HBar->isVisible() ) HBar->setVisible(); } @@ -1518,6 +1702,7 @@ void FListBox::insert ( FString item VBar->setMaximum(element_count - height + 2); VBar->setPageSize(element_count, height - 2); VBar->calculateSliderValues(); + if ( ! VBar->isVisible() && element_count >= height - 1 ) VBar->setVisible(); } @@ -1539,32 +1724,38 @@ void FListBox::remove (int item) return; data.erase (data.begin() + item - 1); - element_count = int(count()); maxLineWidth = 0; for (int i=0; i < element_count; i++) { int len = int(data[uInt(i)].getText().getLength()); + if ( len > maxLineWidth ) maxLineWidth = len; } + HBar->setMaximum(maxLineWidth - width + nf_offset + 4); HBar->setPageSize(maxLineWidth, width - nf_offset - 4); + if ( HBar->isVisible() && maxLineWidth < width - nf_offset - 3 ) HBar->hide(); VBar->setMaximum(element_count - height + 2); VBar->setPageSize(element_count, height - 2); + if ( VBar->isVisible() && element_count < height - 1 ) VBar->hide(); if ( current >= item && current > 1 ) current--; + if ( current > element_count ) current = element_count; + if ( yoffset > element_count - height + 2 ) yoffset = element_count - height + 2; + if ( yoffset < 0 ) yoffset = 0; } @@ -1604,6 +1795,7 @@ void FListBox::clear() gotoxy (xpos+xmin, ypos+ymin+y); print (blank); } + delete[] blank; } diff --git a/src/fmenu.cpp b/src/fmenu.cpp index 5ab73ac5..f2da5910 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -79,8 +79,10 @@ FMenu::~FMenu() { if ( vwin->changes != 0 ) delete[] vwin->changes; + if ( vwin->text != 0 ) delete[] vwin->text; + delete vwin; } } @@ -124,17 +126,21 @@ void FMenu::init(FWidget* parent) if ( isMenuBar(parent) ) { FMenuBar* mbar = dynamic_cast(parent); + if ( mbar ) mbar->menu_dimension(); } else if ( isMenu(parent) ) { FMenu* smenu = dynamic_cast(parent); + if ( smenu ) smenu->menu_dimension(); } + setSuperMenu(parent); } + menu_dimension(); } @@ -194,8 +200,8 @@ void FMenu::menu_dimension() // set sub-menu position (*iter)->getMenu()->setPos (menu_X, menu_Y, false); } - item_Y++; + item_Y++; ++iter; } } @@ -225,6 +231,7 @@ void FMenu::adjustItems() if ( menu->count() > 0 ) menu->adjustItems(); } + ++iter; } } @@ -240,19 +247,10 @@ int FMenu::adjustX (int x_pos) if ( x_pos < 1 ) x_pos = 1; } + return x_pos; } -//---------------------------------------------------------------------- -void FMenu::adjustSize() -{ - //int adjust_X = adjustX(xpos); - - FWidget::adjustSize(); - - //move (adjust_X, ypos); -} - //---------------------------------------------------------------------- bool FMenu::isWindowsMenu (FWidget* w) const { @@ -284,6 +282,7 @@ bool FMenu::isRadioMenuItem (FWidget* w) const bool FMenu::isSubMenu() const { FWidget* super = getSuperMenu(); + if ( super && isMenu(super) ) return true; else @@ -298,15 +297,19 @@ void FMenu::openSubMenu (FMenu* sub_menu) // open sub menu sub_menu->selectFirstItem(); + if ( sub_menu->hasSelectedItem() ) sub_menu->getSelectedItem()->setFocus(); + sub_menu->setVisible(); sub_menu->show(); open_sub_menu = sub_menu; raiseWindow (sub_menu); sub_menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -321,6 +324,7 @@ void FMenu::hideSubMenus() open_sub_menu->hide(); open_sub_menu = 0; } + unselectItem(); } @@ -329,6 +333,7 @@ void FMenu::hideSuperMenus() { // hide all menus to the top FWidget* super = getSuperMenu(); + if ( super ) { if ( isMenuBar(super) ) @@ -374,7 +379,9 @@ FMenu* FMenu::superMenuAt (int x, int y) const // Check mouse click position for super menu if ( getGeometryGlobal().contains(x,y) ) return 0; + FWidget* super = getSuperMenu(); + if ( super && isMenu(super) ) { if ( super->getGeometryGlobal().contains(x,y) ) @@ -385,6 +392,7 @@ FMenu* FMenu::superMenuAt (int x, int y) const return smenu->superMenuAt(x,y); } } + return 0; } @@ -401,33 +409,40 @@ bool FMenu::selectNextItem() { FMenuItem* next; std::vector::const_iterator next_element; - next_element = iter; + do { ++next_element; if ( next_element == itemlist.end() ) next_element = itemlist.begin(); next = static_cast(*next_element); - } while ( ! next->isEnabled() - || ! next->acceptFocus() - || ! next->isVisible() - || next->isSeparator() ); + } + while ( ! next->isEnabled() + || ! next->acceptFocus() + || ! next->isVisible() + || next->isSeparator() ); + if ( next == *iter ) return false; + unselectItem(); next->setSelected(); setSelectedItem(next); redraw(); next->setFocus(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); break; } + ++iter; } + return true; } @@ -441,36 +456,43 @@ bool FMenu::selectPrevItem() do { --iter; + if ( (*iter)->isSelected() ) { FMenuItem* prev; std::vector::const_iterator prev_element; - prev_element = iter; + do { if ( prev_element == itemlist.begin() ) prev_element = itemlist.end(); --prev_element; prev = static_cast(*prev_element); - } while ( ! prev->isEnabled() - || ! prev->acceptFocus() - || ! prev->isVisible() - || prev->isSeparator() ); + } + while ( ! prev->isEnabled() + || ! prev->acceptFocus() + || ! prev->isVisible() + || prev->isSeparator() ); + if ( prev == *iter ) return false; + unselectItem(); prev->setSelected(); setSelectedItem(prev); prev->setFocus(); + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); updateTerminal(); flush_out(); break; } - } while ( iter != begin ); + } + while ( iter != begin ); return true; } @@ -530,11 +552,14 @@ bool FMenu::hotkeyMenu (FKeyEvent*& ev) ev->accept(); (*iter)->processClicked(); } + return true; } } + ++iter; } + return false; } @@ -554,8 +579,10 @@ int FMenu::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) i++; src++; } + *dest++ = *src++; } + return hotkeypos; } @@ -565,15 +592,20 @@ void FMenu::draw() // fill the background setColor (wc.menu_active_fg, wc.menu_active_bg); setUpdateVTerm(false); + if ( isMonochron() ) setReverse(true); + clrscr(); drawBorder(); drawItems(); + if ( isMonochron() ) setReverse(false); + if ( (flags & fc::shadow) != 0 ) drawMenuShadow(); + setUpdateVTerm(true); } @@ -590,8 +622,10 @@ void FMenu::drawBorder() { gotoxy (x1, y1); print (fc::NF_border_corner_upper_left); // ⎡ + for (int x=x1+1; x < x2; x++) print (fc::NF_border_line_upper); // ¯ + print (fc::NF_rev_border_corner_upper_right); // ⎤ for (int y=y1+1; y <= y2; y++) @@ -603,11 +637,14 @@ void FMenu::drawBorder() // border right⎹ print (fc::NF_rev_border_line_right); } + gotoxy (x1, y2); // lower left corner border ⎣ print (fc::NF_border_corner_lower_left); + for (int x=1; x < width-1; x++) // low line _ print (fc::NF_border_line_bottom); + gotoxy (x2, y2); // lower right corner border ⎦ print (fc::NF_rev_border_corner_lower_right); @@ -616,14 +653,17 @@ void FMenu::drawBorder() { gotoxy (x1, y1); print (fc::BoxDrawingsDownAndRight); // ┌ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ - print (fc::BoxDrawingsDownAndLeft); // ┐ + print (fc::BoxDrawingsDownAndLeft); // ┐ gotoxy (x1, y2); print (fc::BoxDrawingsUpAndRight); // └ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::BoxDrawingsUpAndLeft); // ┘ for (int y=y1+1; y < y2; y++) @@ -684,6 +724,7 @@ void FMenu::drawItems() { foregroundColor = wc.menu_active_focus_fg; backgroundColor = wc.menu_active_focus_bg; + if ( isMonochron() ) setReverse(false); } @@ -691,6 +732,7 @@ void FMenu::drawItems() { foregroundColor = wc.menu_active_fg; backgroundColor = wc.menu_active_bg; + if ( isMonochron() ) setReverse(true); } @@ -699,11 +741,14 @@ void FMenu::drawItems() { foregroundColor = wc.menu_inactive_fg; backgroundColor = wc.menu_inactive_bg; + if ( isMonochron() ) setReverse(true); } + gotoxy (xpos+xmin, ypos+ymin+y); setColor (foregroundColor, backgroundColor); + if ( has_checkable_items ) { if ( is_checkable ) @@ -730,18 +775,20 @@ void FMenu::drawItems() else { setColor (wc.menu_inactive_fg, backgroundColor); + if ( getEncoding() == "ASCII" ) print ('-'); else print (fc::SmallBullet); + setColor (foregroundColor, backgroundColor); } } else print (' '); } - print (' '); + print (' '); txt = (*iter)->getText(); txt_length = uInt(txt.getLength()); item_text = new wchar_t[txt_length+1](); @@ -761,6 +808,7 @@ void FMenu::drawItems() if ( is_selected ) setCursorPos ( xpos+xmin+1+hotkeypos , ypos+ymin+y ); // hotkey + txt_length--; to_char--; } @@ -777,22 +825,29 @@ void FMenu::drawItems() item_text[z] = L' '; } } + if ( (z == hotkeypos) && is_enabled && ! is_selected ) { setColor (wc.menu_hotkey_fg, wc.menu_hotkey_bg); + if ( ! is_noUnderline ) setUnderline(); + print (item_text[z]); + if ( ! is_noUnderline ) unsetUnderline(); + setColor (foregroundColor, backgroundColor); } else print (item_text[z]); } + if ( has_menu ) { int len = int(maxItemWidth) - (to_char + c + 3); + if ( len > 0 ) { print (FString(len, wchar_t(' '))); @@ -806,6 +861,7 @@ void FMenu::drawItems() FString accel_name (getKeyName(accel_key)); int accel_len = int(accel_name.getLength()); int len = int(maxItemWidth) - (to_char + accel_len + c + 2); + if ( len > 0 ) { FString spaces (len, wchar_t(' ')); @@ -822,11 +878,14 @@ void FMenu::drawItems() if ( isMonochron() && is_enabled && is_selected ) setReverse(true); + delete[] item_text; } + ++iter; y++; } + if ( hasFocus() ) setCursor(); } @@ -836,8 +895,10 @@ inline void FMenu::drawSeparator(int y) { gotoxy (xpos+xmin-1, ypos+ymin+y); setColor (wc.menu_active_fg, wc.menu_active_bg); + if ( isMonochron() ) setReverse(true); + if ( isNewFont() ) { print (fc::NF_border_line_vertical_right); @@ -852,6 +913,7 @@ inline void FMenu::drawSeparator(int y) print (line); print (fc::BoxDrawingsVerticalAndLeft); } + if ( isMonochron() ) setReverse(false); } @@ -867,15 +929,19 @@ void FMenu::processActivate() //---------------------------------------------------------------------- void FMenu::onKeyPress (FKeyEvent* ev) { + FWidget* menubar; + // looking for menu hotkey if ( hotkeyMenu(ev) ) return; // looking for menu bar hotkey - FWidget* menubar = menuBar(); + menubar = menuBar(); + if ( menubar ) { FMenuBar* mbar = reinterpret_cast(menubar); + if ( mbar->hotkeyMenu(ev) ) return; } @@ -916,8 +982,10 @@ void FMenu::onKeyPress (FKeyEvent* ev) hide(); smenu->getSelectedItem()->setFocus(); smenu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -929,6 +997,7 @@ void FMenu::onKeyPress (FKeyEvent* ev) if ( hasSelectedItem() && getSelectedItem()->hasMenu() ) { FMenu* sub_menu = getSelectedItem()->getMenu(); + if ( ! sub_menu->isVisible() ) openSubMenu (sub_menu); else @@ -943,6 +1012,7 @@ void FMenu::onKeyPress (FKeyEvent* ev) unselectItem(); hideSubMenus(); hide(); + if ( isSubMenu() ) { FMenu* smenu = reinterpret_cast(getSuperMenu()); @@ -952,15 +1022,19 @@ void FMenu::onKeyPress (FKeyEvent* ev) else { hideSuperMenus(); + if ( statusBar() ) statusBar()->clearMessage(); + activatePrevWindow(); raiseWindow (getActiveWindow()); getActiveWindow()->getFocusWidget()->setFocus(); getActiveWindow()->redraw(); } + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); break; @@ -986,11 +1060,14 @@ void FMenu::onMouseDown (FMouseEvent* ev) open_sub_menu = 0; getSelectedItem()->setFocus(); redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } + return; } @@ -1017,7 +1094,6 @@ void FMenu::onMouseDown (FMouseEvent* ev) while ( iter != end ) { int x1, x2, y, mouse_x, mouse_y; - x1 = (*iter)->getX(); x2 = (*iter)->getX() + (*iter)->getWidth(); y = (*iter)->getY(); @@ -1051,6 +1127,7 @@ void FMenu::onMouseDown (FMouseEvent* ev) } } } + if ( ! (*iter)->isSelected() ) { unselectItem(); @@ -1060,19 +1137,24 @@ void FMenu::onMouseDown (FMouseEvent* ev) (*iter)->setSelected(); setSelectedItem(*iter); (*iter)->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + if ( (*iter)->hasMenu() ) { FMenu* sub_menu = (*iter)->getMenu(); if ( ! sub_menu->isVisible() ) show_sub_menu = sub_menu; } + focus_changed = true; } } + ++iter; } @@ -1102,11 +1184,11 @@ void FMenu::onMouseUp (FMouseEvent* ev) if ( mouse_down ) { mouse_down = false; + if ( ! itemlist.empty() ) { std::vector::const_iterator iter, end; FPoint mouse_pos; - iter = itemlist.begin(); end = itemlist.end(); mouse_pos = ev->getPos(); @@ -1115,7 +1197,6 @@ void FMenu::onMouseUp (FMouseEvent* ev) while ( iter != end ) { int x1, x2, y; - x1 = (*iter)->getX(); x2 = (*iter)->getX() + (*iter)->getWidth(); y = (*iter)->getY(); @@ -1138,14 +1219,19 @@ void FMenu::onMouseUp (FMouseEvent* ev) else if ( open_sub_menu ) { open_sub_menu->selectFirstItem(); + if ( open_sub_menu->hasSelectedItem() ) open_sub_menu->getSelectedItem()->setFocus(); + open_sub_menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } + return; } else @@ -1157,8 +1243,10 @@ void FMenu::onMouseUp (FMouseEvent* ev) } } } + ++iter; } + // Click on a non-FMenuItem (border or separator line) unselectItem(); hide(); @@ -1207,6 +1295,7 @@ void FMenu::onMouseMove (FMouseEvent* ev) if ( isSubMenu() ) { smenu = superMenuAt (ev->getGlobalPos()); + if ( smenu ) mouse_over_supermenu = true; } @@ -1221,7 +1310,6 @@ void FMenu::onMouseMove (FMouseEvent* ev) while ( iter != end ) { int x1, x2, y, mouse_x, mouse_y; - x1 = (*iter)->getX(); x2 = (*iter)->getX() + (*iter)->getWidth(); y = (*iter)->getY(); @@ -1243,19 +1331,24 @@ void FMenu::onMouseMove (FMouseEvent* ev) (*iter)->setSelected(); setSelectedItem(*iter); (*iter)->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + // sub menu handling if ( (*iter)->hasMenu() ) { FMenu* sub_menu = (*iter)->getMenu(); + if ( ! sub_menu->isVisible() ) show_sub_menu = sub_menu; } else if ( open_sub_menu ) hide_sub_menu = true; + focus_changed = true; } } @@ -1268,11 +1361,14 @@ void FMenu::onMouseMove (FMouseEvent* ev) { // Unselect selected item without mouse focus (*iter)->unsetSelected(); + if ( getSelectedItem() == *iter ) setSelectedItem(0); + focus_changed = true; } } + ++iter; } @@ -1324,12 +1420,15 @@ void FMenu::onMouseMove (FMouseEvent* ev) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + + if ( curMsg != msg ) if ( curMsg != msg ) { statusBar()->setMessage(msg); statusBar()->drawMessage(); } } + if ( open_sub_menu ) hide_sub_menu = true; } @@ -1345,6 +1444,7 @@ void FMenu::onMouseMove (FMouseEvent* ev) open_sub_menu->hideSubMenus(); open_sub_menu->hide(); } + // open sub menu show_sub_menu->setVisible(); show_sub_menu->show(); @@ -1398,10 +1498,13 @@ void FMenu::hide() if ( ! isSubMenu() ) { FMenu* open_menu = static_cast(getOpenMenu()); + if ( open_menu && open_menu != this ) open_menu->hide(); + setOpenMenu(0); } + mouse_down = false; } } @@ -1412,6 +1515,7 @@ void FMenu::setGeometry (int xx, int yy, int ww, int hh, bool adjust) int old_width = width; int old_height = height; FWidget::setGeometry (xx, yy, ww, hh, adjust); + if ( vwin && (width != old_width || height != old_height) ) resizeArea (vwin); } @@ -1420,6 +1524,7 @@ void FMenu::setGeometry (int xx, int yy, int ww, int hh, bool adjust) void FMenu::setStatusbarMessage(FString msg) { FWidget::setStatusbarMessage(msg); + if ( item ) item->setStatusbarMessage(msg); } @@ -1432,8 +1537,10 @@ void FMenu::cb_menuitem_toggled (FWidget* widget, void*) if ( ! has_checkable_items ) return; + if ( ! menuitem->isChecked() ) return; + if ( itemlist.empty() ) return; @@ -1448,6 +1555,7 @@ void FMenu::cb_menuitem_toggled (FWidget* widget, void*) { (*iter)->unsetChecked(); } + ++iter; } } @@ -1471,7 +1579,7 @@ bool FMenu::setTransparentShadow (bool on) adjustWidgetSizeShadow = getGeometry() + getShadow(); adjustWidgetSizeGlobalShadow = getGeometryGlobal() + getShadow(); } + resizeArea (vwin); return on; } - diff --git a/src/fmenu.h b/src/fmenu.h index 7c037dd6..cf1057b0 100644 --- a/src/fmenu.h +++ b/src/fmenu.h @@ -60,7 +60,6 @@ class FMenu : public FWindow, public FMenuList void menu_dimension(); void adjustItems(); int adjustX(int); - void adjustSize(); bool isWindowsMenu (FWidget*) const; bool isMenuBar (FWidget*) const; bool isMenu (FWidget*) const; diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index f5dcb64e..5dc0cf53 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -26,10 +26,13 @@ FMenuBar::~FMenuBar() { if ( vmenubar->changes != 0 ) delete[] vmenubar->changes; + if ( vmenubar->text != 0 ) delete[] vmenubar->text; + delete vmenubar; } + vmenubar = 0; } @@ -45,7 +48,6 @@ void FMenuBar::init() vmenubar->visible = true; window_object = true; ignore_padding = true; - // initialize geometry values setGeometry (1, 1, getColumnNumber(), 1, false); setMenuBar(this); @@ -104,42 +106,53 @@ bool FMenuBar::selectNextItem() { FMenuItem* next; std::vector::const_iterator next_element; - next_element = iter; + do { ++next_element; + if ( next_element == itemlist.end() ) next_element = itemlist.begin(); + next = static_cast(*next_element); } while ( ! next->isEnabled() || ! next->acceptFocus() || ! next->isVisible() || next->isSeparator() ); + if ( next == *iter ) return false; + unselectItem(); next->setSelected(); setSelectedItem(next); next->setFocus(); + if ( drop_down && next->hasMenu() ) { - FMenuItem* first_item; - FMenu* menu = next->getMenu(); - next->openMenu(); - menu->selectFirstItem(); - first_item = menu->getSelectedItem(); - if ( first_item ) - first_item->setFocus(); - menu->redraw(); + FMenuItem* first_item; + FMenu* menu = next->getMenu(); + next->openMenu(); + menu->selectFirstItem(); + first_item = menu->getSelectedItem(); + + if ( first_item ) + first_item->setFocus(); + + menu->redraw(); } + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); break; } + ++iter; } + return true; } @@ -153,27 +166,33 @@ bool FMenuBar::selectPrevItem() do { --iter; + if ( (*iter)->isSelected() ) { FMenuItem* prev; std::vector::const_iterator prev_element; - prev_element = iter; + do { if ( prev_element == itemlist.begin() ) prev_element = itemlist.end(); + --prev_element; prev = static_cast(*prev_element); - } while ( ! prev->isEnabled() - || ! prev->acceptFocus() - || ! prev->isVisible() - || prev->isSeparator() ); + } + while ( ! prev->isEnabled() + || ! prev->acceptFocus() + || ! prev->isVisible() + || prev->isSeparator() ); + if ( prev == *iter ) return false; + unselectItem(); prev->setSelected(); prev->setFocus(); + if ( drop_down && prev->hasMenu() ) { FMenuItem* first_item; @@ -181,17 +200,22 @@ bool FMenuBar::selectPrevItem() prev->openMenu(); menu->selectFirstItem(); first_item = menu->getSelectedItem(); + if ( first_item ) first_item->setFocus(); + menu->redraw(); } + if ( statusBar() ) statusBar()->drawMessage(); + setSelectedItem(prev); redraw(); break; } - } while ( iter != begin ); + } + while ( iter != begin ); return true; } @@ -229,11 +253,15 @@ bool FMenuBar::hotkeyMenu (FKeyEvent*& ev) (*iter)->openMenu(); menu->selectFirstItem(); first_item = menu->getSelectedItem(); + if ( first_item ) first_item->setFocus(); + menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); drop_down = true; } @@ -244,12 +272,15 @@ bool FMenuBar::hotkeyMenu (FKeyEvent*& ev) drop_down = false; (*iter)->processClicked(); } + ev->accept(); return true; } } + ++iter; } + return false; } @@ -269,8 +300,10 @@ int FMenuBar::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length) i++; src++; } + *dest++ = *src++; } + return hotkeypos; } @@ -288,7 +321,6 @@ void FMenuBar::drawItems() { std::vector::const_iterator iter, end; int screenWidth; - int x = 1; screenWidth = getColumnNumber(); width = screenWidth; @@ -341,6 +373,7 @@ void FMenuBar::drawItems() foregroundColor = wc.menu_inactive_fg; backgroundColor = wc.menu_inactive_bg; } + setColor (foregroundColor, backgroundColor); if ( x < screenWidth ) @@ -374,6 +407,7 @@ void FMenuBar::drawItems() { if ( startpos > screenWidth-z ) break; + if ( ! iswprint(wint_t(item_text[z])) ) { if ( ! isNewFont() && ( int(item_text[z]) < fc::NF_rev_left_arrow2 @@ -382,14 +416,19 @@ void FMenuBar::drawItems() item_text[z] = L' '; } } + if ( (z == hotkeypos) && is_active && ! is_selected ) { setColor (wc.menu_hotkey_fg, wc.menu_hotkey_bg); + if ( ! is_noUnderline ) setUnderline(); + print (vmenubar, item_text[z]); + if ( ! is_noUnderline ) unsetUnderline(); + setColor (foregroundColor, backgroundColor); } else @@ -417,10 +456,11 @@ void FMenuBar::drawItems() } setColor (wc.menu_active_fg, wc.menu_active_bg); + if ( isMonochron() && is_active && is_selected ) setReverse(true); - delete[] item_text; + delete[] item_text; ++iter; } @@ -457,8 +497,8 @@ void FMenuBar::adjustItems() // call menu adjustItems() menu->adjustItems(); } - item_X += item_width; + item_X += item_width; ++iter; } } @@ -468,11 +508,15 @@ void FMenuBar::leaveMenuBar() { resetMenu(); redraw(); + if ( statusBar() ) statusBar()->clearMessage(); + switchToPrevWindow(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); mouse_down = false; @@ -499,11 +543,15 @@ void FMenuBar::onKeyPress (FKeyEvent* ev) sel_item->openMenu(); menu->selectFirstItem(); first_item = menu->getSelectedItem(); + if ( first_item ) first_item->setFocus(); + menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); drop_down = true; } @@ -515,6 +563,7 @@ void FMenuBar::onKeyPress (FKeyEvent* ev) sel_item->processClicked(); } } + ev->accept(); break; @@ -552,7 +601,8 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) return; if ( statusBar() ) - statusBar()->clearMessage(); + statusBar()->clearMessage(); + return; } @@ -593,8 +643,10 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) FApplication::queueEvent(focused_widget, &out); (*iter)->setSelected(); (*iter)->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + (*iter)->openMenu(); setSelectedItem(*iter); focus_changed = true; @@ -602,6 +654,7 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) if ( (*iter)->hasMenu() ) { FMenu* menu = (*iter)->getMenu(); + if ( menu->hasSelectedItem() ) { menu->unselectItem(); @@ -614,11 +667,14 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) else if ( (*iter)->isEnabled() && (*iter)->isSelected() ) { (*iter)->unsetSelected(); + if ( getSelectedItem() == *iter ) setSelectedItem(0); + focus_changed = true; } } + ++iter; } @@ -642,11 +698,11 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) if ( mouse_down ) { mouse_down = false; + if ( ! itemlist.empty() ) { - std::vector::const_iterator iter, end; int mouse_x, mouse_y; - + std::vector::const_iterator iter, end; iter = itemlist.begin(); end = itemlist.end(); mouse_x = ev->getX(); @@ -655,7 +711,6 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) while ( iter != end ) { int x1, x2; - x1 = (*iter)->getX(); x2 = (*iter)->getX() + (*iter)->getWidth(); @@ -669,16 +724,21 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) if ( (*iter)->hasMenu() ) { FMenu* menu = (*iter)->getMenu(); + if ( ! menu->hasSelectedItem() ) { FMenuItem* first_item; menu->selectFirstItem(); first_item = menu->getSelectedItem(); + if ( first_item ) first_item->setFocus(); + menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); drop_down = true; } @@ -686,6 +746,7 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) else { (*iter)->unsetSelected(); + if ( getSelectedItem() == *iter ) { setSelectedItem(0); @@ -699,14 +760,18 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) else { (*iter)->unsetSelected(); + if ( getSelectedItem() == *iter ) setSelectedItem(0); + redraw(); } } + ++iter; } } + if ( ! hasSelectedItem() ) leaveMenuBar(); } @@ -728,7 +793,6 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) int mouse_x, mouse_y; bool mouse_over_menubar = false; bool focus_changed = false; - iter = itemlist.begin(); end = itemlist.end(); mouse_x = ev->getX(); @@ -740,7 +804,6 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) while ( iter != end ) { int x1, x2; - x1 = (*iter)->getX(); x2 = (*iter)->getX() + (*iter)->getWidth(); @@ -756,21 +819,24 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) FApplication::queueEvent(focused_widget, &out); (*iter)->setSelected(); (*iter)->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + (*iter)->openMenu(); setSelectedItem(*iter); focus_changed = true; if ( (*iter)->hasMenu() ) { - FMenu* menu = (*iter)->getMenu(); - if ( menu->hasSelectedItem() ) - { - menu->unselectItem(); - menu->redraw(); - drop_down = true; - } + FMenu* menu = (*iter)->getMenu(); + + if ( menu->hasSelectedItem() ) + { + menu->unselectItem(); + menu->redraw(); + drop_down = true; + } } } else if ( statusBar() ) @@ -784,8 +850,10 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) { // Unselect selected item without mouse focus (*iter)->unsetSelected(); + if ( getSelectedItem() == *iter ) setSelectedItem(0); + focus_changed = true; drop_down = false; } @@ -798,10 +866,11 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) if ( menu->count() > 0 && menu_geometry.contains(ev->getGlobalPos()) ) { + FMouseEvent* _ev; const FPoint& g = ev->getGlobalPos(); const FPoint& p = menu->globalToLocalPos(g); int b = ev->getButton(); - FMouseEvent* _ev = new FMouseEvent (fc::MouseMove_Event, p, g, b); + _ev = new FMouseEvent (fc::MouseMove_Event, p, g, b); menu->mouse_down = true; setClickedWidget(menu); menu->onMouseMove(_ev); @@ -809,10 +878,13 @@ void FMenuBar::onMouseMove (FMouseEvent* ev) } } } + ++iter; } + if ( statusBar() ) statusBar()->drawMessage(); + if ( focus_changed ) { redraw(); @@ -827,8 +899,10 @@ void FMenuBar::onAccel (FAccelEvent* ev) unselectItem(); selectFirstItem(); getSelectedItem()->setFocus(); + if ( statusBar() ) statusBar()->drawMessage(); + redraw(); ev->accept(); } @@ -841,16 +915,13 @@ void FMenuBar::hide() char* blank; FWindow::hide(); - fg = wc.term_fg; bg = wc.term_bg; setColor (fg, bg); - screenWidth = getColumnNumber(); blank = new char[screenWidth+1]; memset(blank, ' ', uLong(screenWidth)); blank[screenWidth] = '\0'; - gotoxy (1,1); print (vmenubar, blank); delete[] blank; @@ -880,6 +951,7 @@ void FMenuBar::setGeometry (int xx, int yy, int ww, int hh, bool adjust) int old_width = width; int old_height = height; FWidget::setGeometry (xx, yy, ww, hh, adjust); + if ( vmenubar && (width != old_width || height != old_height) ) resizeArea (vmenubar); } diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index e7421ffc..4e22a1d0 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -175,12 +175,14 @@ void FMenuItem::init (FWidget* parent) addAccelerator (accel_key); menu_list = dynamic_cast(parent); + if ( menu_list ) menu_list->insert(this); if ( isMenuBar(parent) ) // Parent is menubar { FMenuBar* menubar_ptr = dynamic_cast(parent); + if ( menubar_ptr ) { menubar_ptr->menu_dimension(); @@ -198,10 +200,12 @@ void FMenuItem::init (FWidget* parent) else if ( isMenu(parent) ) // Parent is menu { FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) menu_ptr->menu_dimension(); } } + if ( hasFocus() ) flags = fc::focus; @@ -231,6 +235,7 @@ uChar FMenuItem::hotKey() return 0;; } } + return 0; } @@ -260,13 +265,16 @@ void FMenuItem::createDialogList (FMenu* winmenu) do { --iter; + if ( (*iter)->isDialog() ) { FDialog* win = dynamic_cast(*iter); + if ( win ) { FString win_title = win->getText(); FMenuItem* win_item = new FMenuItem (win_title, winmenu); + win_item->addCallback ( "clicked", @@ -278,6 +286,7 @@ void FMenuItem::createDialogList (FMenu* winmenu) } while ( iter != begin ); } + winmenu->menu_dimension(); } @@ -285,13 +294,16 @@ void FMenuItem::createDialogList (FMenu* winmenu) void FMenuItem::cb_switchToDialog (FWidget*, void* data_ptr) { FDialog* win = static_cast(data_ptr); + if ( win && ! win->isHiddenWindow() && ! win->isActiveWindow() ) { FWindow::setActiveWindow(win); FWidget* focus_widget = win->getFocusWidget(); FWindow::raiseWindow (win); + if ( focus_widget ) focus_widget->setFocus(); + win->redraw(); } } @@ -333,6 +345,7 @@ bool FMenuItem::isMenu (FWidget* w) const void FMenuItem::addAccelerator (int key, FWidget* obj) { FWidget* super = super_menu; + if ( ! super ) return; @@ -349,6 +362,7 @@ void FMenuItem::addAccelerator (int key, FWidget* obj) if ( ! window ) window = getRootWidget(); + if ( window && window->accelerator_list ) { accel_key = key; @@ -359,6 +373,7 @@ void FMenuItem::addAccelerator (int key, FWidget* obj) if ( isMenu(super_menu) ) { FMenu* menu_ptr = dynamic_cast(super_menu); + if ( menu_ptr ) menu_ptr->menu_dimension(); } @@ -368,6 +383,7 @@ void FMenuItem::addAccelerator (int key, FWidget* obj) void FMenuItem::delAccelerator (FWidget* obj) { FWidget* super = super_menu; + if ( ! super ) return; @@ -383,6 +399,7 @@ void FMenuItem::delAccelerator (FWidget* obj) if ( ! window ) window = getRootWidget(); + if ( window && window->accelerator_list && ! window->accelerator_list->empty() ) @@ -406,6 +423,7 @@ void FMenuItem::delAccelerator (FWidget* obj) if ( isMenu(super_menu) ) { FMenu* menu_ptr = dynamic_cast(super_menu); + if ( menu_ptr ) menu_ptr->menu_dimension(); } @@ -419,6 +437,7 @@ void FMenuItem::onKeyPress (FKeyEvent* ev) if ( isMenu(super_menu) ) { FMenu* smenu = dynamic_cast(super_menu); + if ( smenu ) smenu->onKeyPress(ev); } @@ -426,10 +445,12 @@ void FMenuItem::onKeyPress (FKeyEvent* ev) if ( isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { if ( mbar->hotkeyMenu(ev) ) return; + mbar->onKeyPress(ev); } } @@ -447,6 +468,7 @@ void FMenuItem::onMouseDoubleClick (FMouseEvent* ev) if ( isMenu(super_menu) ) { FMenu* smenu = dynamic_cast(super_menu); + if ( smenu ) { const FPoint& p2 = smenu->globalToLocalPos(g); @@ -459,6 +481,7 @@ void FMenuItem::onMouseDoubleClick (FMouseEvent* ev) if ( isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { const FPoint& p2 = mbar->globalToLocalPos(g); @@ -471,6 +494,7 @@ void FMenuItem::onMouseDoubleClick (FMouseEvent* ev) if ( isWindowsMenu(super_menu) ) { FDialog* dgl = dynamic_cast(super_menu); + if ( dgl ) { const FPoint& p2 = dgl->globalToLocalPos(g); @@ -493,6 +517,7 @@ void FMenuItem::onMouseDown (FMouseEvent* ev) if ( isMenu(super_menu) ) { FMenu* smenu = dynamic_cast(super_menu); + if ( smenu ) { const FPoint& p2 = smenu->globalToLocalPos(g); @@ -505,6 +530,7 @@ void FMenuItem::onMouseDown (FMouseEvent* ev) if ( isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { const FPoint& p2 = mbar->globalToLocalPos(g); @@ -517,6 +543,7 @@ void FMenuItem::onMouseDown (FMouseEvent* ev) if ( isWindowsMenu(super_menu) ) { FDialog* dgl = dynamic_cast(super_menu); + if ( dgl ) { const FPoint& p2 = dgl->globalToLocalPos(g); @@ -539,6 +566,7 @@ void FMenuItem::onMouseUp (FMouseEvent* ev) if ( isMenu(super_menu) ) { FMenu* smenu = dynamic_cast(super_menu); + if ( smenu ) { const FPoint& p2 = smenu->globalToLocalPos(g); @@ -551,6 +579,7 @@ void FMenuItem::onMouseUp (FMouseEvent* ev) if ( isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { const FPoint& p2 = mbar->globalToLocalPos(g); @@ -563,6 +592,7 @@ void FMenuItem::onMouseUp (FMouseEvent* ev) if ( isWindowsMenu(super_menu) ) { FDialog* dgl = dynamic_cast(super_menu); + if ( dgl ) { const FPoint& p2 = dgl->globalToLocalPos(g); @@ -585,6 +615,7 @@ void FMenuItem::onMouseMove (FMouseEvent* ev) if ( isMenu(super_menu) ) { FMenu* smenu = dynamic_cast(super_menu); + if ( smenu ) { const FPoint& p2 = smenu->globalToLocalPos(g); @@ -597,6 +628,7 @@ void FMenuItem::onMouseMove (FMouseEvent* ev) if ( isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { const FPoint& p2 = mbar->globalToLocalPos(g); @@ -609,6 +641,7 @@ void FMenuItem::onMouseMove (FMouseEvent* ev) if ( isWindowsMenu(super_menu) ) { FDialog* dgl = dynamic_cast(super_menu); + if ( dgl ) { const FPoint& p2 = dgl->globalToLocalPos(g); @@ -628,6 +661,7 @@ void FMenuItem::onAccel (FAccelEvent* ev) if ( super_menu && isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) { if ( menu ) @@ -636,6 +670,7 @@ void FMenuItem::onAccel (FAccelEvent* ev) if ( mbar->getSelectedItem() ) mbar->getSelectedItem()->unsetSelected(); + setSelected(); mbar->selectedItem = this; openMenu(); @@ -646,11 +681,15 @@ void FMenuItem::onAccel (FAccelEvent* ev) menu->unselectItem(); menu->selectFirstItem(); menu->getSelectedItem()->setFocus(); + if ( focused_widget ) focused_widget->redraw(); + menu->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + mbar->redraw(); mbar->drop_down = true; } @@ -681,12 +720,15 @@ void FMenuItem::onFocusIn (FFocusEvent*) void FMenuItem::onFocusOut (FFocusEvent*) { unsetSelected(); + if ( super_menu && isMenuBar(super_menu) ) { FMenuBar* mbar = dynamic_cast(super_menu); + if ( mbar ) mbar->redraw(); } + if ( statusBar() ) { statusBar()->clearMessage(); @@ -698,7 +740,6 @@ void FMenuItem::onFocusOut (FFocusEvent*) bool FMenuItem::setEnable (bool on) { FWidget::setEnable(on); - FWidget* super = getSuperMenu(); if ( on ) @@ -718,6 +759,7 @@ bool FMenuItem::setEnable (bool on) if ( super && isMenuBar(super) ) super->delAccelerator (this); } + return on; } @@ -736,6 +778,7 @@ bool FMenuItem::setFocus (bool on) { FMenuList* menu_list = dynamic_cast(getSuperMenu()); setSelected(); + if ( menu_list ) { menu_list->unselectItem(); @@ -746,15 +789,18 @@ bool FMenuItem::setFocus (bool on) statusBar()->drawMessage(); FWidget* parent = getSuperMenu(); + if ( isMenuBar(parent) ) { FMenuBar* menubar_ptr = dynamic_cast(parent); + if ( menubar_ptr ) menubar_ptr->redraw(); } else if ( isMenu(parent) ) { FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) menu_ptr->redraw(); } @@ -764,6 +810,7 @@ bool FMenuItem::setFocus (bool on) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) statusBar()->setMessage(msg); } @@ -776,6 +823,7 @@ bool FMenuItem::setFocus (bool on) if ( isEnabled() && statusBar() ) statusBar()->clearMessage(); } + return on; } @@ -805,19 +853,22 @@ void FMenuItem::openMenu() if ( hasMenu() ) { 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_list ) createDialogList (dd_menu); - setOpenMenu(dd_menu); + setOpenMenu(dd_menu); dd_menu->setVisible(); dd_menu->show(); dd_menu->raiseWindow(dd_menu); @@ -833,8 +884,10 @@ void FMenuItem::setText (FString& txt) text = txt; text_length = text.getLength(); hotkey = hotKey(); + if ( hotkey ) text_length--; + setWidth(int(text_length)); } diff --git a/src/fmenulist.cpp b/src/fmenulist.cpp index 0e68dfbf..48a548a3 100644 --- a/src/fmenulist.cpp +++ b/src/fmenulist.cpp @@ -55,6 +55,7 @@ void FMenuList::selectFirstItem() setSelectedItem(*iter); break; } + ++iter; } } @@ -64,6 +65,7 @@ void FMenuList::unselectItem() { if ( hasSelectedItem() ) getSelectedItem()->unsetSelected(); + setSelectedItem(0); } @@ -82,6 +84,7 @@ void FMenuList::remove (FMenuItem* i) return; iter = itemlist.begin(); + while ( iter != itemlist.end() ) { if ( (*iter) == i ) @@ -109,4 +112,3 @@ void FMenuList::clear() { itemlist.clear(); } - diff --git a/src/fmessagebox.cpp b/src/fmessagebox.cpp index 315b8242..f4afe15b 100644 --- a/src/fmessagebox.cpp +++ b/src/fmessagebox.cpp @@ -109,8 +109,10 @@ void FMessageBox::init(int button0, int button1, int button2) { button0 = button1 = button2 = 0; } + if ( button0 == 0 ) button0 = FMessageBox::Ok; + if ( button1 == 0 && button2 == 0 ) numButtons = 1; else if ( button2 == 0 ) @@ -157,29 +159,34 @@ void FMessageBox::init(int button0, int button1, int button2) adjustButtons(); if ( *button_digit[0] != 0 ) + { button[0]->addCallback ( "clicked", _METHOD_CALLBACK (this, &FMessageBox::cb_processClick), static_cast(button_digit[0]) ); - + } if ( *button_digit[1] != 0 ) + { button[1]->addCallback ( "clicked", _METHOD_CALLBACK (this, &FMessageBox::cb_processClick), static_cast(button_digit[1]) ); + } if ( *button_digit[2] != 0 ) + { button[2]->addCallback ( "clicked", _METHOD_CALLBACK (this, &FMessageBox::cb_processClick), static_cast(button_digit[2]) ); + } setModal(); setTransparentShadow(); @@ -201,13 +208,17 @@ void FMessageBox::msg_dimension() for (uInt i=0; i < text_num_lines; i++) { uInt len = text_components[i].getLength(); + if ( len > maxLineWidth ) maxLineWidth = len; } + h = int(text_num_lines) + 8 + headline_height; w = int(maxLineWidth + 4); + if ( w < 20 ) w = 20; + x = 1 + int((getParentWidget()->getWidth()-w)/2); y = 1 + int((getParentWidget()->getHeight()-h)/3); setGeometry (x, y, w, h); @@ -221,7 +232,6 @@ void FMessageBox::draw() int head_offset = 0; int center_x = 0; int msg_x = int((width - int(maxLineWidth)) / 2); // center the whole block - setUpdateVTerm(false); if ( isMonochron() ) @@ -231,8 +241,10 @@ void FMessageBox::draw() { setColor(emphasis_color, backgroundColor); uInt headline_length = headline_text.getLength(); + if ( center_text ) // center one line center_x = int((maxLineWidth - headline_length) / 2); + gotoxy (xpos+xmin-1+msg_x+center_x, ypos+ymin+2); print (headline_text); head_offset = 2; @@ -243,8 +255,10 @@ void FMessageBox::draw() for (int i=0; i < int(text_num_lines); i++) { uInt line_length = text_components[i].getLength(); + if ( center_text ) // center one line center_x = int((maxLineWidth - line_length) / 2); + gotoxy (xpos+xmin-1+msg_x+center_x, ypos+ymin+2+head_offset+i); print(text_components[i]); } @@ -259,9 +273,11 @@ void FMessageBox::draw() void FMessageBox::resizeButtons() { uInt len[3], max_size; + for (uInt n=0; n < numButtons; n++) { len[n] = button[n]->getText().getLength(); + if ( button[n]->getText().includes('&') ) len[n]--; } @@ -272,9 +288,11 @@ void FMessageBox::resizeButtons() { assert ( numButtons > 1 ); max_size = std::max(len[0], len[1]); + if ( numButtons == 3 ) max_size = std::max(max_size, len[2]); } + if ( max_size < 7 ) max_size = 7; @@ -287,6 +305,7 @@ void FMessageBox::adjustButtons() { int btn_width=0; int gap = 4; + for (uInt n=0; n < numButtons; n++) { if ( n == numButtons-1 ) @@ -381,11 +400,15 @@ void FMessageBox::setHeadline (const FString& headline) int old_height = height; headline_text = headline; setHeight(height + 2, true); + for (uInt n=0; n < numButtons; n++) button[n]->setY(height-4, false); + uInt len = headline_text.getLength(); + if ( len > maxLineWidth ) maxLineWidth = len; + if ( vwin && height != old_height ) resizeArea (vwin); } @@ -410,10 +433,13 @@ void FMessageBox::setText (const FString& txt) text = txt; msg_dimension(); button[0]->setY(height-4, false); + if ( *button_digit[1] != 0 ) button[1]->setY(height-4, false); + if ( *button_digit[2] != 0 ) button[2]->setY(height-4, false); + adjustButtons(); } diff --git a/src/fobject.cpp b/src/fobject.cpp index 85388932..f6aabdef 100644 --- a/src/fobject.cpp +++ b/src/fobject.cpp @@ -49,6 +49,7 @@ FObject::~FObject() // destructor // delete children objects FObject::object_list children = this->getChildren(); + if ( ! children.empty() ) { FObject::object_list::const_iterator iter; @@ -92,6 +93,7 @@ bool FObject::event (FEvent* ev) onTimer ( static_cast(ev) ); return true; } + return false; } @@ -106,6 +108,7 @@ void FObject::getCurrentTime (timeval &time) time.tv_usec -= 1000000; time.tv_sec++; } + while ( time.tv_usec < 0 ) { if ( time.tv_sec > 0 ) @@ -196,8 +199,8 @@ bool FObject::delTimer (int id) modify_timer = false; return true; } - modify_timer = false; + modify_timer = false; return false; } @@ -208,6 +211,7 @@ bool FObject::delOwnTimer() if ( ! timer_list ) return false; + if ( timer_list->empty() ) return false; @@ -221,8 +225,8 @@ bool FObject::delOwnTimer() else ++iter; } - modify_timer = false; + modify_timer = false; return true; } @@ -231,13 +235,13 @@ bool FObject::delAllTimer() { if ( ! timer_list ) return false; + if ( timer_list->empty() ) return false; modify_timer = true; timer_list->clear(); modify_timer = false; - return true; } diff --git a/src/fobject.h b/src/fobject.h index 6b888174..d0cfba5d 100644 --- a/src/fobject.h +++ b/src/fobject.h @@ -134,11 +134,13 @@ static inline timeval operator + (const timeval& t1, const timeval& t2) { timeval tmp; tmp.tv_sec = t1.tv_sec + t2.tv_sec; + if ( (tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000 ) { tmp.tv_sec++; tmp.tv_usec -= 1000000; } + return tmp; } @@ -147,11 +149,13 @@ static inline timeval operator - (const timeval& t1, const timeval& t2) { timeval tmp; tmp.tv_sec = t1.tv_sec - t2.tv_sec; + if ( (tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0 ) { tmp.tv_sec--; tmp.tv_usec += 1000000; } + return tmp; } @@ -159,11 +163,13 @@ static inline timeval operator - (const timeval& t1, const timeval& t2) static inline timeval& operator += (timeval& t1, const timeval& t2) { t1.tv_sec += t2.tv_sec; + if ( (t1.tv_usec += t2.tv_usec) >= 1000000 ) { t1.tv_sec++; t1.tv_usec -= 1000000; } + return t1; } diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index cb7cb212..f5538be5 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -135,6 +135,7 @@ inline void FOptiAttr::prevent_no_color_video_attributes (char_data*& attr) if ( attr->reverse ) { attr->reverse = false; + if ( attr->fg_color != attr->bg_color ) fake_reverse = true; } @@ -216,10 +217,12 @@ void FOptiAttr::change_color (char_data*& term, char_data*& next) { char* sgr_49; char* op = F_orig_pair.cap; + if ( op && strncmp (op, CSI "39;49;25m", 11) == 0 ) sgr_49 = const_cast(CSI "49;25m"); else sgr_49 = const_cast(CSI "49m"); + append_sequence (sgr_49); term->bg_color = Default; } @@ -238,6 +241,7 @@ void FOptiAttr::change_color (char_data*& term, char_data*& next) if ( fake_reverse ) { std::swap (fg, bg); + if ( fg == Default || bg == Default ) setTermDefaultColor(term); } @@ -257,9 +261,11 @@ void FOptiAttr::change_color (char_data*& term, char_data*& next) if ( ansi_fg != Default ) { color_str = tparm(AF, ansi_fg); + if ( color_str ) append_sequence (color_str); } + if ( ansi_bg != Default ) { color_str = tparm(AB, ansi_bg); @@ -352,15 +358,20 @@ bool FOptiAttr::caused_reset_attributes (char*& cap, uChar test) { if ( (test & test_ansi_reset) && strncmp (cap, CSI "m", 3) == 0 ) return true; + if ( (test & test_adm3_reset) && strncmp (cap, ESC "G0", 3) == 0 ) return true; + if ( (test & same_like_ue) && ue && strcmp (cap, ue) == 0 ) return true; + if ( (test & same_like_se) && se && strcmp (cap, se) == 0 ) return true; + if ( (test & same_like_me) && me && strcmp (cap, me) == 0 ) return true; } + return false; } @@ -460,6 +471,7 @@ inline bool FOptiAttr::unsetTermBold (char_data*& term) term->bold = false; term->dim = false; } + return true; } else @@ -488,6 +500,7 @@ inline bool FOptiAttr::unsetTermDim (char_data*& term) term->bold = false; term->dim = false; } + return true; } else @@ -512,6 +525,7 @@ inline bool FOptiAttr::unsetTermItalic (char_data*& term) reset(term); else term->italic = false; + return true; } else @@ -540,6 +554,7 @@ inline bool FOptiAttr::unsetTermUnderline (char_data*& term) term->underline = false; term->dbl_underline = false; } + return true; } else @@ -564,6 +579,7 @@ inline bool FOptiAttr::unsetTermBlink (char_data*& term) reset(term); else term->blink = false; + return true; } else @@ -588,6 +604,7 @@ inline bool FOptiAttr::unsetTermReverse (char_data*& term) reset(term); else term->reverse = false; + return true; } else @@ -612,6 +629,7 @@ inline bool FOptiAttr::unsetTermStandout (char_data*& term) reset(term); else term->standout = false; + return true; } else @@ -636,6 +654,7 @@ inline bool FOptiAttr::unsetTermInvisible (char_data*& term) reset(term); else term->invisible = false; + return true; } else @@ -660,6 +679,7 @@ inline bool FOptiAttr::unsetTermProtected (char_data*& term) reset(term); else term->protect = false; + return true; } else @@ -684,6 +704,7 @@ inline bool FOptiAttr::unsetTermCrossedOut (char_data*& term) reset(term); else term->crossed_out = false; + return true; } else @@ -712,6 +733,7 @@ inline bool FOptiAttr::unsetTermDoubleUnderline (char_data*& term) term->underline = false; term->dbl_underline = false; } + return true; } else @@ -1289,6 +1311,7 @@ char* FOptiAttr::change_attribute (char_data*& term, char_data*& next) { if ( off.pc_charset ) unsetTermPCcharset(term); + if ( off.alt_charset ) unsetTermAltCharset(term); @@ -1300,28 +1323,39 @@ char* FOptiAttr::change_attribute (char_data*& term, char_data*& next) { if ( off.bold ) unsetTermBold(term); + if ( off.dim ) unsetTermDim(term); + if ( off.italic ) unsetTermItalic(term); + if ( off.underline ) unsetTermUnderline(term); + if ( off.blink ) unsetTermBlink(term); + if ( off.reverse ) unsetTermReverse(term); + if ( off.standout ) unsetTermStandout(term); + if ( off.invisible ) unsetTermInvisible(term); + if ( off.protect ) unsetTermProtected(term); + if ( off.crossed_out ) unsetTermCrossedOut(term); + if ( off.dbl_underline ) unsetTermDoubleUnderline(term); } } + if ( colorChange(term, next) ) change_color (term, next); } @@ -1341,24 +1375,31 @@ char* FOptiAttr::change_attribute (char_data*& term, char_data*& next) , next->invisible , next->protect , next->alt_charset ); + if ( next->italic ) setTermItalic(term); + if ( next->crossed_out ) setTermCrossedOut(term); + if ( next->dbl_underline ) setTermDoubleUnderline(term); + if ( next->pc_charset ) setTermPCcharset(term); if ( colorChange(term, next) ) { change_color (term, next); + if ( cygwin_terminal ) { if ( next->bold ) setTermBold(term); + if ( next->reverse ) setTermReverse(term); + if ( next->standout ) setTermStandout(term); } @@ -1368,28 +1409,40 @@ char* FOptiAttr::change_attribute (char_data*& term, char_data*& next) { if ( off.pc_charset ) unsetTermPCcharset(term); + if ( off.alt_charset ) unsetTermAltCharset(term); + if ( off.bold ) unsetTermBold(term); + if ( off.dim ) unsetTermDim(term); + if ( off.italic ) unsetTermItalic(term); + if ( off.underline ) unsetTermUnderline(term); + if ( off.blink ) unsetTermBlink(term); + if ( off.reverse ) unsetTermReverse(term); + if ( off.standout ) unsetTermStandout(term); + if ( off.invisible ) unsetTermInvisible(term); + if ( off.protect ) unsetTermProtected(term); + if ( off.crossed_out ) unsetTermCrossedOut(term); + if ( off.dbl_underline ) unsetTermDoubleUnderline(term); @@ -1402,30 +1455,43 @@ char* FOptiAttr::change_attribute (char_data*& term, char_data*& next) change_color (term, next); detectSwitchOn (term, next); + if ( on.pc_charset ) setTermPCcharset(term); + if ( on.alt_charset ) setTermAltCharset(term); + if ( on.bold ) setTermBold(term); + if ( on.dim ) setTermDim(term); + if ( on.italic ) setTermItalic(term); + if ( on.underline ) setTermUnderline(term); + if ( on.blink ) setTermBlink(term); + if ( on.reverse ) setTermReverse(term); + if ( on.standout ) setTermStandout(term); + if ( on.invisible ) setTermInvisible(term); + if ( on.protect ) setTermProtected(term); + if ( on.crossed_out ) setTermCrossedOut(term); + if ( on.dbl_underline ) setTermDoubleUnderline(term); } diff --git a/src/foptimove.cpp b/src/foptimove.cpp index 93f372e7..e895d1cf 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -54,6 +54,7 @@ void FOptiMove::calculateCharDuration() const int baudbyte = 9; // = 7 bit + 1 parity + 1 stop char_duration = (baudbyte * 1000 * 10) / (baudrate > 0 ? baudrate : 9600); // milliseconds + if ( char_duration <= 0 ) char_duration = 1; } @@ -89,11 +90,13 @@ int FOptiMove::cap_duration (char*& cap, int affcnt) else if ( *p == '.' && *++p != '>' && isdigit(uChar(*p)) ) num += float((*p - '0') / 10.0); } + ms += num * 10; } else ms += float(char_duration); } + return int(ms); } else @@ -324,9 +327,11 @@ int FOptiMove::repeated_append (capability& o, int count, char* dst) if ( (dst_len + uInt(count) * src_len) < sizeof(move_buf)-1 ) { total += count * o.duration; + if ( dst ) { dst += dst_len; + while ( count-- > 0 ) { strcpy (dst, o.cap); @@ -360,6 +365,7 @@ int FOptiMove::relative_move ( char*& move { if ( move ) strcpy (move, tparm(F_row_address.cap, to_y)); + vtime = F_row_address.duration; } @@ -371,6 +377,7 @@ int FOptiMove::relative_move ( char*& move { if ( move ) strcpy (move, tparm(F_parm_down_cursor.cap, num)); + vtime = F_parm_down_cursor.duration; } @@ -378,6 +385,7 @@ int FOptiMove::relative_move ( char*& move { if ( move ) move[0] = '\0'; + vtime = repeated_append (F_cursor_down, num, move); } } @@ -389,6 +397,7 @@ int FOptiMove::relative_move ( char*& move { if ( move ) strcpy (move, tparm(F_parm_up_cursor.cap, num)); + vtime = F_parm_up_cursor.duration; } @@ -396,6 +405,7 @@ int FOptiMove::relative_move ( char*& move { if ( move ) move[0] = '\0'; + vtime = repeated_append (F_cursor_up, num, move); } } @@ -446,11 +456,15 @@ int FOptiMove::relative_move ( char*& move if ( tab_pos > to_x ) break; + htime_r += repeated_append (F_tab, 1, str); + if ( htime_r >= LONG_DURATION ) break; + pos = tab_pos; } + num = to_x - pos; } @@ -461,6 +475,7 @@ int FOptiMove::relative_move ( char*& move strcpy (hmove, str); htime = htime_r; } + } } else // to_x < from_x @@ -484,17 +499,22 @@ int FOptiMove::relative_move ( char*& move if ( tabstop > 0 && F_back_tab.cap ) { int pos = from_x; + while ( true ) { int tab_pos = ( pos > 0 ) ? ((pos-1)/tabstop)*tabstop : -1; if ( tab_pos < to_x ) break; + htime_l += repeated_append (F_back_tab, 1, str); + if ( htime_l >= LONG_DURATION ) break; + pos = tab_pos; } + num = pos - to_x; } @@ -505,6 +525,7 @@ int FOptiMove::relative_move ( char*& move strcpy (hmove, str); htime = htime_l; } + } } @@ -572,6 +593,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) if ( xold >= 0 && yold >= 0 ) { new_time = relative_move (null_ptr, xold, yold, xnew, ynew); + if ( new_time < LONG_DURATION && new_time < move_time ) { method = 1; @@ -583,6 +605,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) if ( yold >= 0 && F_carriage_return.cap ) { new_time = relative_move (null_ptr, 0, yold, xnew, ynew); + if ( new_time < LONG_DURATION && F_carriage_return.duration + new_time < move_time ) { @@ -595,6 +618,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) if ( F_cursor_home.cap ) { new_time = relative_move (null_ptr, 0, 0, xnew, ynew); + if ( new_time < LONG_DURATION && F_cursor_home.duration + new_time < move_time ) { @@ -607,6 +631,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) if ( F_cursor_to_ll.cap ) { new_time = relative_move (null_ptr, 0, screen_height-1, xnew, ynew); + if ( new_time < LONG_DURATION && F_cursor_to_ll.duration + new_time < move_time ) { @@ -622,6 +647,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) && F_cursor_left.cap ) { new_time = relative_move (null_ptr, screen_width-1, yold-1, xnew, ynew); + if ( new_time < LONG_DURATION && F_carriage_return.cap && F_carriage_return.duration @@ -664,10 +690,12 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) case 5: move_buf[0] = '\0'; + if ( xold >= 0 ) strncat ( move_ptr , F_carriage_return.cap , sizeof(move_buf) - strlen(move_ptr) - 1 ); + strncat ( move_ptr , F_cursor_left.cap , sizeof(move_buf) - strlen(move_ptr) - 1 ); @@ -679,6 +707,7 @@ char* FOptiMove::cursor_move (int xold, int yold, int xnew, int ynew) break; } } + if ( move_time < LONG_DURATION ) return move_buf; else diff --git a/src/fprogressbar.cpp b/src/fprogressbar.cpp index 22a4d29b..bb726887 100644 --- a/src/fprogressbar.cpp +++ b/src/fprogressbar.cpp @@ -27,13 +27,17 @@ void FProgressbar::drawPercentage() { setColor ( getParentWidget()->getForegroundColor() , getParentWidget()->getBackgroundColor() ); + if ( isMonochron() ) setReverse(true); + gotoxy (xpos+xmin+width-5, ypos+ymin-2); + if ( percentage < 0 || percentage > 100 ) print ("--- %"); else printf ("%3d %%", percentage); + if ( isMonochron() ) setReverse(false); } @@ -43,8 +47,8 @@ void FProgressbar::drawBar() { int i = 1; float length = float(BarLength*percentage)/100; - gotoxy (xpos+xmin-1, ypos+ymin-1); + if ( isMonochron() ) { if ( round(length) >= 1) @@ -60,6 +64,7 @@ void FProgressbar::drawBar() { setColor ( wc.progressbar_bg , wc.progressbar_fg ); + if ( round(length) >= 1) print (' '); else @@ -86,10 +91,13 @@ void FProgressbar::drawBar() setColor ( wc.progressbar_bg , wc.progressbar_fg ); + if ( isMonochron() ) setReverse(false); + for (; i < trunc(length); i++) print (' '); + if ( isMonochron() ) setReverse(true); @@ -113,10 +121,12 @@ void FProgressbar::drawBar() setColor (wc.progressbar_fg, wc.progressbar_bg); print (fc::LeftHalfBlock); // ▌ } + i++; } setColor (wc.progressbar_fg, wc.progressbar_bg); + if ( getMaxColor() < 16 ) { for (; i < BarLength; i++) @@ -127,6 +137,7 @@ void FProgressbar::drawBar() for (; i < BarLength; i++) print (' '); } + if ( isMonochron() ) setReverse(false); @@ -145,6 +156,7 @@ void FProgressbar::draw() if ( (flags & fc::shadow) != 0 ) drawShadow (); + setUpdateVTerm(true); flush_out(); } @@ -159,11 +171,9 @@ void FProgressbar::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); - s = hasShadow() ? 1 : 0; size = width + s; blank = new char[size+1]; @@ -175,8 +185,8 @@ void FProgressbar::hide() gotoxy (xpos+xmin-1, ypos+ymin-1+y); print (blank); } - delete[] blank; + delete[] blank; gotoxy (xpos+xmin+width-5, ypos+ymin-2); print (" "); // hide percentage } @@ -195,11 +205,13 @@ void FProgressbar::setPercentage (int percentage_value) percentage = percentage_value; setUpdateVTerm(false); + if ( isVisible() ) { drawPercentage(); drawBar(); } + setUpdateVTerm(true); updateTerminal(); } @@ -209,11 +221,13 @@ void FProgressbar::reset() { setUpdateVTerm(false); percentage = -1; + if ( isVisible() ) { drawPercentage(); drawBar(); } + setUpdateVTerm(true); updateTerminal(); } @@ -234,6 +248,7 @@ bool FProgressbar::setEnable (bool on) flags |= fc::active; else flags &= ~fc::active; + return on; } @@ -246,5 +261,6 @@ bool FProgressbar::setShadow (bool on) flags |= fc::shadow; else flags &= ~fc::shadow; + return on; } diff --git a/src/fradiobutton.cpp b/src/fradiobutton.cpp index 8f1d9b6e..5c39e373 100644 --- a/src/fradiobutton.cpp +++ b/src/fradiobutton.cpp @@ -45,7 +45,6 @@ void FRadioButton::draw() drawRadioButton(); drawLabel(); setUpdateVTerm(true); - FToggleButton::draw(); } @@ -65,6 +64,7 @@ void FRadioButton::drawRadioButton() else setReverse(true); } + if ( checked ) { if ( isNewFont() ) @@ -87,7 +87,7 @@ void FRadioButton::drawRadioButton() print (')'); } } + if ( isMonochron() ) setReverse(false); } - diff --git a/src/fradiomenuitem.cpp b/src/fradiomenuitem.cpp index d99a8849..f1ac177f 100644 --- a/src/fradiomenuitem.cpp +++ b/src/fradiomenuitem.cpp @@ -54,6 +54,7 @@ void FRadioMenuItem::init (FWidget* parent) if ( isMenu(parent) ) // Parent is menu { FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) menu_ptr->has_checkable_items = true; diff --git a/src/fscrollbar.cpp b/src/fscrollbar.cpp index 2c937d22..efb91c02 100644 --- a/src/fscrollbar.cpp +++ b/src/fscrollbar.cpp @@ -91,6 +91,7 @@ void FScrollbar::draw() int FScrollbar::getClickedScrollType (int x, int y) { int stype; + if ( bar_orientation == fc::vertical ) { if ( y == 1 ) @@ -157,6 +158,7 @@ int FScrollbar::getClickedScrollType (int x, int y) stype = FScrollbar::noScroll; } } + return stype; } @@ -164,6 +166,7 @@ int FScrollbar::getClickedScrollType (int x, int y) void FScrollbar::processMiddleButton (int x, int y) { int new_val; + if ( bar_orientation == fc::vertical ) { if ( y >1 && y < height ) @@ -177,6 +180,7 @@ void FScrollbar::processMiddleButton (int x, int y) else // horizontal { int nf = isNewFont() ? 1 : 0; + if ( x > 1+nf && x < width-nf ) { new_val = int( round ( float(max-min) * (x-2.0-nf-(SliderLength/2)) @@ -185,6 +189,7 @@ void FScrollbar::processMiddleButton (int x, int y) else return; } + if ( new_val != val ) { setValue(new_val); @@ -313,11 +318,11 @@ void FScrollbar::onMouseMove (FMouseEvent* ev) if ( scrollType == FScrollbar::scrollJump ) { int new_val; + if ( bar_orientation == fc::vertical ) { int dy = mouse_y - SliderClickPos; SliderClickPos = mouse_y; - new_val = int( round ( float((max-min) * (SliderPos + dy)) / float(BarLength-SliderLength) ) ); } @@ -325,10 +330,10 @@ void FScrollbar::onMouseMove (FMouseEvent* ev) { int dx = mouse_x - SliderClickPos; SliderClickPos = mouse_x; - new_val = int( round ( float((max-min) * (SliderPos + dx)) / float(BarLength-SliderLength) ) ); } + if ( new_val != val ) { setValue(new_val); @@ -449,6 +454,7 @@ void FScrollbar::setSteps (float st) steps = 1; else steps = st; + if ( pageSize == 0 ) pageSize = int(float(max)/steps); } @@ -475,6 +481,7 @@ void FScrollbar::calculateSliderValues() BarLength = length - 4; else BarLength = length - 2; + SliderLength = int(float(BarLength) / steps); if ( SliderLength < 1 ) @@ -487,6 +494,7 @@ void FScrollbar::calculateSliderValues() SliderPos = 0; return; } + if ( val == max ) { SliderPos = BarLength - SliderLength; @@ -517,6 +525,7 @@ void FScrollbar::setOrientation (int o) { height = 1; width = length; + if ( isNewFont() ) nf = 2; } @@ -541,6 +550,7 @@ void FScrollbar::setGeometry (int x, int y, int w, int h, bool adjust) { height = 1; width = length; + if ( isNewFont() ) nf = 2; } @@ -558,19 +568,25 @@ void FScrollbar::drawBar() if ( bar_orientation == fc::vertical ) { setColor (wc.scrollbar_fg, wc.scrollbar_bg); + for (z=1; z <= SliderPos; z++) { gotoxy (xpos+xmin-1, ypos+ymin-1+z); + if ( isNewFont() ) print (fc::NF_border_line_left); // ⎸ + if ( isMonochron() || max_color < 16 ) print (fc::MediumShade); // ▒ else print (' '); } + setColor (wc.scrollbar_bg, wc.scrollbar_fg); + if ( isMonochron() ) setReverse(false); + for (z=1; z <= SliderLength; z++) { gotoxy (xpos+xmin-1, ypos+ymin-1+SliderPos+z); @@ -578,14 +594,19 @@ void FScrollbar::drawBar() print (' '); print (' '); } + if ( isMonochron() ) setReverse(true); + setColor (wc.scrollbar_fg, wc.scrollbar_bg); + for (z=SliderPos+SliderLength+1; z <= BarLength; z++) { gotoxy (xpos+xmin-1, ypos+ymin-1+z); + if ( isNewFont() ) print (fc::NF_border_line_left); // ⎸ + if ( isMonochron() || max_color < 16 ) print (fc::MediumShade); else @@ -595,8 +616,8 @@ void FScrollbar::drawBar() else // horizontal { setColor (wc.scrollbar_fg, wc.scrollbar_bg); - z = 0; + if ( isNewFont() ) gotoxy (xpos+xmin+1+z, ypos+ymin-1); else @@ -611,17 +632,23 @@ void FScrollbar::drawBar() else print (' '); } + setColor (wc.scrollbar_bg, wc.scrollbar_fg); + if ( isMonochron() ) setReverse(false); z = 0; + for (; z < SliderLength; z++) print (' '); + if ( isMonochron() ) setReverse(true); + setColor (wc.scrollbar_fg, wc.scrollbar_bg); z = SliderPos + SliderLength + 1; + for (; z <= BarLength; z++) { if ( isNewFont() ) @@ -632,6 +659,7 @@ void FScrollbar::drawBar() print (' '); } } + currentSliderPos = SliderPos; if ( isMonochron() ) @@ -680,7 +708,9 @@ void FScrollbar::drawButtons() print ('^'); else print (fc::BlackUpPointingTriangle); // ▲ + gotoxy (xpos+xmin-1, ypos+ymin+length-2); + if ( isCygwinTerminal() ) print ('v'); else @@ -693,6 +723,7 @@ void FScrollbar::drawButtons() print (fc::BlackRightPointingPointer); // ► } + if ( isMonochron() ) setReverse(false); } diff --git a/src/fstatusbar.cpp b/src/fstatusbar.cpp index c4286bbd..07774d67 100644 --- a/src/fstatusbar.cpp +++ b/src/fstatusbar.cpp @@ -62,6 +62,7 @@ FStatusKey::~FStatusKey() // destructor { if ( statusbar() ) statusbar()->remove(this); + delAccelerator(); } @@ -154,10 +155,13 @@ FStatusBar::~FStatusBar() { if ( vstatusbar->changes != 0 ) delete[] vstatusbar->changes; + if ( vstatusbar->text != 0 ) delete[] vstatusbar->text; + delete vstatusbar; } + vstatusbar = 0; // delete all keys @@ -213,7 +217,6 @@ void FStatusBar::drawKeys() { std::vector::const_iterator iter, end; int screenWidth, lastLine; - x = 1; screenWidth = getColumnNumber(); lastLine = getLineNumber(); @@ -238,25 +241,27 @@ void FStatusBar::drawKeys() while ( iter != end ) { int kname_len = int(getKeyName((*iter)->getKey()).getLength()); + if ( x+kname_len+2 < screenWidth ) { if ( (*iter)->isActivated() || (*iter)->hasMouseFocus() ) { + int txt_length; if ( isMonochron() ) setReverse(false); + setColor ( wc.statusbar_active_hotkey_fg , wc.statusbar_active_hotkey_bg ); x++; print (vstatusbar, ' '); x += kname_len; print (vstatusbar, getKeyName((*iter)->getKey())); - setColor (wc.statusbar_active_fg, wc.statusbar_active_bg); x++; print (vstatusbar, '-'); - - int txt_length = int((*iter)->getText().getLength()); + txt_length = int((*iter)->getText().getLength()); x += txt_length; + if ( x <= screenWidth ) { print (vstatusbar, (*iter)->getText()); @@ -270,6 +275,7 @@ void FStatusBar::drawKeys() .left(uInt(txt_length+screenWidth-x-1)) ); print (vstatusbar, ".."); } + if ( isMonochron() ) setReverse(true); } @@ -281,16 +287,14 @@ void FStatusBar::drawKeys() setColor (wc.statusbar_hotkey_fg, wc.statusbar_hotkey_bg); x++; print (vstatusbar, ' '); - x += kname_len; print (vstatusbar, getKeyName((*iter)->getKey())); - setColor (wc.statusbar_fg, wc.statusbar_bg); x++; print (vstatusbar, '-'); - txt_length = int((*iter)->getText().getLength()); x += txt_length; + if ( x-1 <= screenWidth ) print (vstatusbar, (*iter)->getText()); else @@ -300,6 +304,7 @@ void FStatusBar::drawKeys() .left(uInt(txt_length+screenWidth-x-1)) ); print ( vstatusbar, ".." ); } + if ( iter+1 != keylist.end() && ( (*(iter+1))->isActivated() || (*(iter+1))->hasMouseFocus() ) && x + int(getKeyName((*(iter+1))->getKey()).getLength()) + 3 @@ -308,9 +313,11 @@ void FStatusBar::drawKeys() // next element is active if ( isMonochron() ) setReverse(false); + setColor (wc.statusbar_active_fg, wc.statusbar_active_bg); x++; print (vstatusbar, fc::LeftHalfBlock); // ▐ + if ( isMonochron() ) setReverse(true); } @@ -326,6 +333,7 @@ void FStatusBar::drawKeys() else { setColor (wc.statusbar_fg, wc.statusbar_bg); + for (; x <= screenWidth; x++) print (vstatusbar, ' '); } @@ -345,9 +353,11 @@ void FStatusBar::onMouseDown (FMouseEvent* ev) { if ( hasActivatedKey() ) return; + if ( ev->getButton() != fc::LeftButton ) { mouse_down = false; + if ( ! keylist.empty() ) { std::vector::const_iterator iter, end; @@ -360,18 +370,20 @@ void FStatusBar::onMouseDown (FMouseEvent* ev) ++iter; } } + redraw(); return; } + if ( mouse_down ) return; + mouse_down = true; if ( ! keylist.empty() ) { std::vector::const_iterator iter, end; int X = 1; - iter = keylist.begin(); end = keylist.end(); @@ -394,6 +406,7 @@ void FStatusBar::onMouseDown (FMouseEvent* ev) (*iter)->setMouseFocus(); redraw(); } + X = x2 + 2; ++iter; } @@ -405,24 +418,24 @@ void FStatusBar::onMouseUp (FMouseEvent* ev) { if ( hasActivatedKey() ) return; + if ( ev->getButton() != fc::LeftButton ) return; if ( mouse_down ) { mouse_down = false; + if ( ! keylist.empty() ) { std::vector::const_iterator iter, end; int X = 1; - iter = keylist.begin(); end = keylist.end(); while ( iter != end ) { int x1, x2, kname_len, txt_length; - x1 = X; kname_len = int(getKeyName((*iter)->getKey()).getLength()); txt_length = int((*iter)->getText().getLength()); @@ -434,12 +447,15 @@ void FStatusBar::onMouseUp (FMouseEvent* ev) (*iter)->unsetMouseFocus(); mouse_x = ev->getX(); mouse_y = ev->getY(); + if ( mouse_x >= x1 && mouse_x <= x2 && mouse_y == 1 ) (*iter)->setActive(); + // unset after get back from callback (*iter)->unsetActive(); redraw(); } + X = x2 + 2; ++iter; } @@ -452,6 +468,7 @@ void FStatusBar::onMouseMove (FMouseEvent* ev) { if ( hasActivatedKey() ) return; + if ( ev->getButton() != fc::LeftButton ) return; @@ -460,21 +477,19 @@ void FStatusBar::onMouseMove (FMouseEvent* ev) std::vector::const_iterator iter, end; bool focus_changed = false; int X=1; - iter = keylist.begin(); end = keylist.end(); while ( iter != end ) { int x1, x2, mouse_x, mouse_y, kname_len, txt_length; - x1 = X; kname_len = int(getKeyName((*iter)->getKey()).getLength()); txt_length = int((*iter)->getText().getLength()); x2 = x1 + kname_len + txt_length + 1; - mouse_x = ev->getX(); mouse_y = ev->getY(); + if ( mouse_x >= x1 && mouse_x <= x2 && mouse_y == 1 ) @@ -493,9 +508,11 @@ void FStatusBar::onMouseMove (FMouseEvent* ev) focus_changed = true; } } + X = x2 + 2; ++iter; } + if ( focus_changed ) redraw(); } @@ -509,17 +526,14 @@ void FStatusBar::hide() char* blank; FWindow::hide(); - fg = wc.term_fg; bg = wc.term_bg; setColor (fg, bg); - lastLine = getLineNumber(); screenWidth = getColumnNumber(); blank = new char[screenWidth+1]; memset(blank, ' ', uLong(screenWidth)); blank[screenWidth] = '\0'; - gotoxy (1, lastLine); print (vstatusbar, blank); delete[] blank; @@ -531,6 +545,7 @@ void FStatusBar::setGeometry (int xx, int yy, int ww, int hh, bool adjust) int old_width = width; int old_height = height; FWidget::setGeometry (xx, yy, ww, hh, adjust); + if ( vstatusbar && (width != old_width || height != old_height) ) resizeArea (vstatusbar); } @@ -548,9 +563,11 @@ bool FStatusBar::hasActivatedKey() { if ( (*iter)->isActivated() ) return true; + ++iter; } } + return false; } @@ -562,6 +579,7 @@ void FStatusBar::drawMessage() if ( ! isVisible() ) return; + if ( x < 0 || x_msg < 0 ) return; @@ -586,8 +604,10 @@ void FStatusBar::drawMessage() setUpdateVTerm(false); setColor (wc.statusbar_fg, wc.statusbar_bg); gotoxy (x, lastLine); + if ( isMonochron() ) setReverse(true); + if ( x+space_offset+3 < termWidth ) { if ( text ) @@ -597,6 +617,7 @@ void FStatusBar::drawMessage() x++; print (vstatusbar, ' '); } + if ( hasKeys ) { x += 2; @@ -606,6 +627,7 @@ void FStatusBar::drawMessage() int msg_length = int(getMessage().getLength()); x += msg_length; + if ( x-1 <= termWidth ) print (vstatusbar, getMessage()); else @@ -616,6 +638,7 @@ void FStatusBar::drawMessage() } } } + for (int i=x; i <= termWidth; i++) print (vstatusbar, ' '); @@ -670,6 +693,7 @@ void FStatusBar::remove (FStatusKey* skey) return; iter = keylist.begin(); + while ( iter != keylist.end() ) { if ( (*iter) == skey ) @@ -726,8 +750,10 @@ void FStatusBar::cb_statuskey_activated (FWidget* widget, void*) ++iter; } } + if ( isVisible() && isShown() ) redraw(); + if ( ! isHiddenCursor() ) hideCursor(); } diff --git a/src/fstring.cpp b/src/fstring.cpp index fd3c57c3..4f3d65f7 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -207,6 +207,7 @@ FString::~FString() // destructor { if ( string ) delete[](string); + if ( c_string ) delete[](c_string); } @@ -260,6 +261,7 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) // string is null length = len; bufsize = FWDBUFFER + length + 1; + try { string = new wchar_t[bufsize](); @@ -269,6 +271,7 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) std::cerr << bad_alloc_str << " " << ex.what() << std::endl; return; } + wcscpy (string, s); return; } @@ -281,8 +284,10 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) // output string <= bufsize for (x = length; x > pos-1; x--) // shifting right side + '\0' string[x+len] = string[x]; + for (x=0; x < len; x++) // insert string string[x+pos] = s[x]; + length += len; } else @@ -300,13 +305,18 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t* s) std::cerr << bad_alloc_str << " " << ex.what() << std::endl; return; } + uInt y = 0; + for (x=0; x < pos; x++) // left side sptr[y++] = string[x]; + for (x=0; x < len; x++) // insert string sptr[y++] = s[x]; + for (x=pos; x < length+1; x++) // right side + '\0' sptr[y++] = string[x]; + length += len; delete[](string); // delete old string string = sptr; @@ -322,6 +332,7 @@ inline void FString::_remove (uInt pos, uInt len) // shifting left side to pos for (uInt i=pos; (i+len) < length+1; i++) string[i] = string[i+len]; + length -= len; } else @@ -338,11 +349,15 @@ inline void FString::_remove (uInt pos, uInt len) std::cerr << bad_alloc_str << " " << ex.what() << std::endl; return; } + uInt x, y = 0; + for (x=0; x < pos; x++) // left side sptr[y++] = string[x]; + for (x=pos+len; x < length+1; x++) // right side + '\0' sptr[y++] = string[x]; + delete[](string); // delete old string string = sptr; length -= len; @@ -357,6 +372,7 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const if ( ! s ) // handle NULL string return 0; + if ( ! *s ) // handle empty string { try @@ -369,8 +385,10 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const std::cerr << bad_alloc_str << " " << ex.what() << std::endl; return 0; } + return c_string; } + if ( c_string ) delete[](c_string); @@ -401,6 +419,7 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const c_string = 0; return const_cast(""); } + return c_string; } @@ -413,6 +432,7 @@ inline wchar_t* FString::c_to_wc_str (const char* s) const if ( ! s ) // handle NULL string return 0; + if ( ! *s ) // handle empty string { try @@ -457,8 +477,10 @@ inline wchar_t* FString::c_to_wc_str (const char* s) const return 0; } } + if ( wclength == size ) dest[size-1] = '\0'; + if ( wclength ) return dest; else @@ -495,6 +517,7 @@ std::ostream& operator << (std::ostream& outstr, const FString& s) { if ( s.length ) outstr << s.wc_to_c_str( s.string ); + return (outstr); } @@ -512,6 +535,7 @@ std::istream& operator >> (std::istream& instr, FString& s) s._replace (wc_str); delete[] wc_str; } + return (instr); } @@ -520,6 +544,7 @@ std::wostream& operator << (std::wostream& outstr, const FString& s) { if ( s.length ) outstr << s.string; + return (outstr); } @@ -539,6 +564,7 @@ FString& FString::operator = (const FString& s) _replace (s.string); else clear(); + return (*this); } @@ -549,6 +575,7 @@ FString& FString::operator = (const std::wstring& s) _replace (s.c_str()); else clear(); + return (*this); } @@ -559,6 +586,7 @@ const FString& FString::operator = (const wchar_t* s) _replace (s); else clear(); + return (*this); } @@ -566,6 +594,7 @@ const FString& FString::operator = (const wchar_t* s) FString& FString::operator = (const std::string& s) { const wchar_t* wc_string = c_to_wc_str(s.c_str()); + if ( wc_string ) { _replace( wc_string ); @@ -573,6 +602,7 @@ FString& FString::operator = (const std::string& s) } else clear(); + return (*this); } @@ -580,6 +610,7 @@ FString& FString::operator = (const std::string& s) const FString& FString::operator = (const char* s) { const wchar_t* wc_string = c_to_wc_str(s); + if ( wc_string ) { _replace( wc_string ); @@ -587,6 +618,7 @@ const FString& FString::operator = (const char* s) } else clear(); + return (*this); } @@ -635,11 +667,13 @@ const FString& FString::operator += (const wchar_t* s) const FString& FString::operator += (const std::string& s) { const wchar_t* wc_string = c_to_wc_str(s.c_str()); + if ( wc_string ) { _insert (length, uInt(s.length()), wc_string); delete[] wc_string; } + return (*this); } @@ -647,11 +681,13 @@ const FString& FString::operator += (const std::string& s) const FString& FString::operator += (const char* s) { const wchar_t* wc_string = c_to_wc_str(s); + if ( wc_string ) { _insert (length, uInt(strlen(s)), wc_string); delete[] wc_string; } + return (*this); } @@ -704,11 +740,12 @@ const FString FString::operator + (const std::string& s) { FString tmp(string); 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); delete[] wc_string; - return (tmp); } @@ -717,11 +754,12 @@ const FString FString::operator + (const char* s) { FString tmp(string); wchar_t* wc_string = c_to_wc_str(s); + if ( ! wc_string ) return (tmp); + tmp._insert (length, uInt(wcslen(wc_string)), wc_string); delete[] wc_string; - return (tmp); } @@ -841,8 +879,10 @@ wchar_t& FString::operator [] (int pos) wchar_t& FString::operator [] (uInt pos) { assert ( (pos < length) && "Invalid index position!" ); + if (pos >= length) throw std::out_of_range(""); + return string[pos]; } @@ -910,11 +950,13 @@ FString& FString::sprintf (const char* format, ...) } wc_string = c_to_wc_str(buffer); + if ( wc_string ) { _replace(wc_string); delete[] wc_string; } + if ( buffer != buf ) delete[] buffer; @@ -926,10 +968,10 @@ FString FString::clear() { if ( string ) delete[](string); + length = 0; bufsize = 0; string = 0; - return (*this); } @@ -966,6 +1008,7 @@ FString FString::toLower() const p++; } } + return s; } @@ -984,6 +1027,7 @@ FString FString::toUpper() const p++; } } + return s; } @@ -1070,11 +1114,13 @@ long FString::toLong() const while ( isdigit(*p) ) { register uChar d = uChar((*p) - L'0'); + if ( num > tenth_limit || (num == tenth_limit && d > tenth_limit_digit) ) { throw std::overflow_error ("overflow"); } + num = (num<<3)+(num<<1) + d; // (10 * num) + d p++; } @@ -1114,11 +1160,13 @@ uLong FString::toULong() const while ( isdigit(*p) ) { register uChar d = uChar((*p) - L'0'); + if ( num > tenth_limit || (num == tenth_limit && d > tenth_limit_digit) ) { throw std::overflow_error ("overflow"); } + num = (num<<3)+(num<<1) + d; // (10 * num) + d p++; } @@ -1162,9 +1210,11 @@ double FString::toDouble() const { if ( ret >= HUGE_VAL || ret <= -HUGE_VAL ) throw std::overflow_error ("overflow"); + if ( fabs(ret) < DBL_EPSILON ) // ret == 0.0l throw std::underflow_error ("underflow"); } + return ret; } @@ -1177,9 +1227,12 @@ FString FString::ltrim() const // handle NULL and empty string if ( ! string || ! *string ) return s; + p = s.string; + while ( iswspace(uInt(*p)) ) p++; + return FString(p); } @@ -1193,9 +1246,12 @@ FString FString::rtrim() const // handle NULL and empty string if ( ! string || ! *string ) return s; + p = s.string; last = p + length; + while ( iswspace(uInt(*--last)) && last > p ); + if ( last == p && iswspace(uInt(*last)) ) s.clear(); else @@ -1210,6 +1266,7 @@ FString FString::trim() const // handle NULL and empty string if ( ! string || ! *string ) return (*this); + FString s(ltrim()); return s.rtrim(); } @@ -1223,8 +1280,10 @@ FString FString::left(uInt len) const // handle NULL and empty string if ( ! string || ! *string ) return s; + if ( len > length ) return s; + p = s.string; *(p+len) = '\0'; return s; @@ -1239,8 +1298,10 @@ FString FString::right(uInt len) const // handle NULL and empty string if ( ! string || ! *string ) return s; + if ( len > length ) return s; + p = s.string; p += (length-len); return FString(p); @@ -1256,10 +1317,13 @@ FString FString::mid(uInt pos, uInt len) const // handle NULL and empty string if ( ! string || ! *string ) return s; + if ( pos == 0 ) pos = 1; + if ( pos <= length && pos+len > length ) len = length - pos + 1; + if ( pos > length || pos+len-1 > length || len == 0 ) return FString(L""); @@ -1289,6 +1353,7 @@ std::vector FString::split (const FString& delimiter) stringList.push_back (FString(token)); token = extractToken (&rest, 0, delimiter.wc_str()); } + return stringList; } @@ -1303,11 +1368,13 @@ FString& FString::setString (const wchar_t* s) FString& FString::setString (const char* s) { const wchar_t* wc_string = c_to_wc_str(s); + if ( wc_string ) { _replace (wc_string); delete[] wc_string; } + return (*this); } @@ -1329,15 +1396,19 @@ FString& FString::setNumber (long num) { neg = false; } + *s = '\0'; + do { *--s = wchar_t(int(num%10) + '0'); num /= 10; - } while ( num ); + } + while ( num ); if ( neg ) *--s = '-'; + _replace (s); return *this; } @@ -1355,10 +1426,10 @@ FString& FString::setNumber (uLong num) { *--s = wchar_t(int(num%10) + '0'); num /= 10; - } while ( num ); + } + while ( num ); _replace (s); - return *this; } @@ -1386,7 +1457,6 @@ FString& FString::setNumber (lDouble num, int precision) *s++ = L'L'; *s++ = L'g'; *s = L'\0'; - return sprintf(format, num); } @@ -1413,17 +1483,22 @@ FString& FString::setFormatedNumber (long num, char separator) { neg = false; } + *s = L'\0'; + do { *--s = wchar_t(int(num%10) + '0'); num /= 10; + if ( num && ++n % 3 == 0 ) *--s = separator; - } while ( num ); + } + while ( num ); if ( neg ) *--s = '-'; + _replace (s); return *this; } @@ -1446,13 +1521,14 @@ FString& FString::setFormatedNumber (uLong num, char separator) { *--s = wchar_t(int(num%10) + '0'); num /= 10; + if ( num && ++n % 3 == 0 ) *--s = separator; - } while ( num ); + } + while ( num ); _replace (s); - return *this; } @@ -1462,12 +1538,16 @@ bool FString::operator < (const FString& s) const { if ( ! s ) return false; + if ( string && ! s.string ) return false; + if ( ! string && s.string ) return true; + if ( ! string && ! s.string ) return false; + return (wcscmp(string, s.string) < 0); } @@ -1518,12 +1598,16 @@ bool FString::operator <= (const FString& s) const { if ( ! s ) return false; + if ( string && ! s.string ) return false; + if ( ! string && s.string ) return true; + if ( ! string && ! s.string ) return true; + return (wcscmp(string, s.string) <= 0); } @@ -1574,10 +1658,13 @@ bool FString::operator == (const FString& s) const { if ( ! s ) return false; + if ( (string && ! s.string ) || (! string && s.string) ) return false; + if ( ! string && ! s.string ) return true; + return (wcscmp(string, s.string) == 0); } @@ -1628,10 +1715,13 @@ bool FString::operator != (const FString& s) const { if ( ! s ) return true; + if ( (string && ! s.string ) || (! string && s.string) ) return true; + if ( ! string && ! s.string ) return false; + return (wcscmp(string, s.string) != 0); } @@ -1682,12 +1772,16 @@ bool FString::operator >= (const FString& s) const { if ( ! s ) return true; + if ( string && ! s.string ) return true; + if ( ! string && s.string ) return false; + if ( ! string && ! s.string ) return true; + return (wcscmp(string, s.string) >= 0); } @@ -1738,12 +1832,16 @@ bool FString::operator > (const FString& s) const { if ( ! s ) return true; + if ( string && ! s.string ) return true; + if ( ! string && s.string ) return false; + if ( ! string && ! s.string ) return false; + return (wcscmp(string, s.string) > 0); } @@ -1795,6 +1893,7 @@ const FString& FString::insert (const FString& s, uInt pos) // assert (pos <= length); if ( pos >= length ) throw std::out_of_range(""); + _insert (pos, s.length, s.string); return (*this); } @@ -1805,6 +1904,7 @@ const FString& FString::insert (const wchar_t* s, uInt pos) // assert (pos <= length); if ( pos >= length ) throw std::out_of_range(""); + _insert (pos, uInt(wcslen(s)), s); return (*this); } @@ -1837,12 +1937,15 @@ FString FString::replace (const FString& from, const FString& to) // handle NULL and empty string if ( ! string || ! *string ) return s; + if ( from.isNull() || to.isNull() ) return s; + p = s.string; from_length = from.getLength(); to_length = to.getLength(); pos = 0; + while ( *p ) { if ( wcsncmp(p, from.string, from_length) == 0 ) @@ -2118,11 +2221,14 @@ FString FString::replace (const wchar_t from, const FString& to) // handle NULL and empty string if ( ! string || ! *string ) return s; + if ( to.isNull() ) return s; + p = s.string; uInt to_length = to.getLength(); uInt pos = 0; + while ( *p ) { if ( wchar_t(*p) == from ) @@ -2138,6 +2244,7 @@ FString FString::replace (const wchar_t from, const FString& to) p++; } } + return s; } @@ -2234,12 +2341,15 @@ FString FString::replace (const char from, const char to) return s; p = s.string; + while ( *p ) { if ( char(*p) == from ) *p = to; + p++; } + return s; } @@ -2269,9 +2379,11 @@ FString FString::replaceControlCodes() const } else if ( ! iswprint(wint_t(*p)) ) *p = L' '; + p++; } } + return s; } @@ -2285,11 +2397,13 @@ FString FString::expandTabs (uInt tabstop) const tab_split = instr.split("\t"); last = tab_split.size(); + for (uInt i=0; i < last; i++) { uInt len = tab_split[i].getLength(); outstr += tab_split[i] + FString(tabstop - len % tabstop, L' '); } + return outstr; } @@ -2304,7 +2418,8 @@ FString FString::removeDel() const if ( p ) { uInt i=0; - uInt d=0; + uInt d=0; + while ( *p ) { if ( *p == 0x7f ) @@ -2320,11 +2435,14 @@ FString FString::removeDel() const s.string[i] = *p; i++; } + p++; } + s.string[i] = L'\0'; s.length = i; } + return s; } @@ -2340,6 +2458,7 @@ FString FString::removeBackspaces() const if ( p ) { uInt i=0; + while ( *p ) { if ( *p != L'\b' ) @@ -2351,11 +2470,14 @@ FString FString::removeBackspaces() const { i--; } + p++; } + s.string[i] = L'\0'; s.length = i; } + return s; } @@ -2371,6 +2493,7 @@ const FString& FString::overwrite (const FString& s, uInt pos) wcsncpy (string + pos, s.string, length - pos); _insert (length, pos + s.length - length, s.string + length - pos); } + return (*this); } @@ -2378,6 +2501,7 @@ const FString& FString::overwrite (const FString& s, uInt pos) const FString& FString::overwrite (const wchar_t* s, uInt pos) { uInt len = uInt(wcslen(s)); + if (length >= (pos+len) ) { wcsncpy (string + pos, s, len); @@ -2387,6 +2511,7 @@ const FString& FString::overwrite (const wchar_t* s, uInt pos) wcsncpy (string + pos, s, length - pos); _insert (length, pos + len - length, s + length - pos); } + return (*this); } @@ -2397,6 +2522,7 @@ const FString& FString::overwrite (const wchar_t c, uInt pos) { string[pos] = c; } + return (*this); } @@ -2405,6 +2531,7 @@ const FString& FString::remove (uInt pos, uInt len) { assert ((pos < length) && ((pos + len) <= length)); _remove (pos, len); + return (*this); } @@ -2425,8 +2552,10 @@ bool FString::includes (const char* s) { bool ret; const wchar_t* wc_string = c_to_wc_str(s); + if ( ! wc_string ) return false; + ret = bool(wcsstr(string, wc_string) != 0); delete[] wc_string; return (ret); diff --git a/src/fswitch.cpp b/src/fswitch.cpp index 6513a99b..e394b08c 100644 --- a/src/fswitch.cpp +++ b/src/fswitch.cpp @@ -41,7 +41,6 @@ void FSwitch::draw() drawLabel(); drawCheckButton(); setUpdateVTerm(true); - FToggleButton::draw(); updateTerminal(); flush_out(); @@ -75,10 +74,12 @@ void FSwitch::drawCheckButton() setColor (wc.button_hotkey_fg, wc.button_active_focus_bg); } else + { if ( isMonochron() || getMaxColor() < 16 ) setColor (wc.button_active_focus_fg, wc.button_active_bg); else setColor (wc.button_hotkey_fg, wc.button_active_bg); + } if ( isMonochron() ) setReverse(false); @@ -93,8 +94,10 @@ void FSwitch::drawCheckButton() setColor (wc.button_inactive_fg, wc.button_inactive_bg); print (off); + if ( isMonochron() ) setReverse(false); + setCursorPos ( xpos + xmin + 1 + switch_offset_pos , ypos + ymin - 1 ); } @@ -123,10 +126,12 @@ void FSwitch::drawCheckButton() setColor (wc.button_hotkey_fg, wc.button_active_focus_bg); } else + { if ( isMonochron() || getMaxColor() < 16 ) setColor (wc.button_active_focus_fg, wc.button_active_bg); else setColor (wc.button_hotkey_fg, wc.button_active_bg); + } if ( isMonochron() ) setReverse(false); diff --git a/src/fterm.cpp b/src/fterm.cpp index f810c67b..9e11c99b 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -203,6 +203,7 @@ int FTerm::getFramebuffer_bpp () return -1; fb = const_cast("/dev/fb0"); + if ( (fd = open(fb, O_RDWR)) < 0 ) return -1; } @@ -248,6 +249,7 @@ int FTerm::closeConsole() int ret = ::close (fd_tty); // use 'close' from the global namespace fd_tty = -1; + if ( ret == 0 ) return 0; else @@ -269,6 +271,7 @@ void FTerm::identifyTermType() { // Import the untrusted environment variable TERM const char* term_env = getenv(const_cast("TERM")); + if ( term_env ) { strncpy (termtype, term_env, sizeof(termtype) - 1); @@ -297,6 +300,7 @@ void FTerm::identifyTermType() // get term basename const char* term_basename = strrchr(term_name, '/'); + if ( term_basename == 0 ) term_basename = term_name; else @@ -316,8 +320,10 @@ void FTerm::identifyTermType() type = p; else if ( name == 0 && p != str && p[-1] == '\0' ) name = p; + p++; } + if ( type != 0 && name != 0 && ! strcmp(name, term_basename) ) { strncpy (termtype, type, sizeof(termtype) - 1); @@ -325,9 +331,11 @@ void FTerm::identifyTermType() return; } } + fclose(fp); } } + // use vt100 if not found strncpy (termtype, const_cast("vt100"), 6); } @@ -417,6 +425,7 @@ int FTerm::setScreenFont ( uChar* fontdata, uInt count { if ( ! direct ) delete[] font.data; + return -1; } @@ -443,6 +452,7 @@ int FTerm::getUnicodeMap() // get count ret = ioctl (fd_tty, GIO_UNIMAP, &unimap); + if ( ret != 0 ) { int count; @@ -493,11 +503,13 @@ int FTerm::setUnicodeMap (struct unimapdesc* unimap) { // clear the unicode-to-font table ret = ioctl(fd_tty, PIO_UNIMAPCLR, &advice); + if ( ret != 0 ) return -1; // put the new unicode-to-font mapping in kernel ret = ioctl(fd_tty, PIO_UNIMAP, unimap); + if ( ret != 0 ) advice.advised_hashlevel++; } @@ -542,14 +554,15 @@ bool FTerm::isKeyTimeout (timeval* time, register long timeout) struct timeval diff; FObject::getCurrentTime(now); - diff.tv_sec = now.tv_sec - time->tv_sec; diff.tv_usec = now.tv_usec - time->tv_usec; + if ( diff.tv_usec < 0 ) { diff.tv_sec--; diff.tv_usec += 1000000; } + diff_usec = (diff.tv_sec * 1000000) + diff.tv_usec; return (diff_usec > timeout); } @@ -569,10 +582,12 @@ int FTerm::parseKeyString ( char* buffer // x11 mouse tracking if ( buf_len >= 6 && buffer[1] == '[' && buffer[2] == 'M' ) return fc::Fkey_mouse; + // SGR mouse tracking if ( buffer[1] == '[' && buffer[2] == '<' && buf_len >= 9 && (buffer[buf_len-1] == 'M' || buffer[buf_len-1] == 'm') ) return fc::Fkey_extended_mouse; + // urxvt mouse tracking if ( buffer[1] == '[' && buffer[2] >= '1' && buffer[2] <= '9' && buffer[3] >= '0' && buffer[3] <= '9' && buf_len >= 9 @@ -588,10 +603,13 @@ int FTerm::parseKeyString ( char* buffer if ( k && strncmp(k, buffer, uInt(len)) == 0 ) // found { n = len; + for (; n < buf_size; n++) // Remove founded entry buffer[n-len] = buffer[n]; + for (; n-len < len; n++) // Fill rest with '\0' buffer[n-len] = '\0'; + input_data_pending = bool(buffer[0] != '\0'); return Fkey[i].num; } @@ -602,6 +620,7 @@ int FTerm::parseKeyString ( char* buffer { char* kmeta = Fmetakey[i].string; // The string is never null len = int(strlen(kmeta)); + if ( strncmp(kmeta, buffer, uInt(len)) == 0 ) // found { if ( len == 2 && ( buffer[1] == 'O' @@ -612,14 +631,18 @@ int FTerm::parseKeyString ( char* buffer return NEED_MORE_DATA; } n = len; + for (; n < buf_size; n++) // Remove founded entry buffer[n-len] = buffer[n]; + for (; n-len < len; n++) // Fill rest with '\0' buffer[n-len] = '\0'; + input_data_pending = bool(buffer[0] != '\0'); return Fmetakey[i].num; } } + if ( ! isKeyTimeout(time_keypressed, key_timeout) ) return NEED_MORE_DATA; } @@ -631,12 +654,14 @@ int FTerm::parseKeyString ( char* buffer if ( utf8_input && (firstchar & 0xc0) == 0xc0 ) { char utf8char[4] = {}; // init array with '\0' + if ((firstchar & 0xe0) == 0xc0) len = 2; else if ((firstchar & 0xf0) == 0xe0) len = 3; else if ((firstchar & 0xf8) == 0xf0) len = 4; + for (n=0; n < len ; n++) utf8char[n] = char(buffer[n] & 0xff); @@ -646,10 +671,13 @@ int FTerm::parseKeyString ( char* buffer key = uChar(buffer[0] & 0xff); n = len; + for (; n < buf_size; n++) // remove the key from the buffer front buffer[n-len] = buffer[n]; + for (n=n-len; n < buf_size; n++) // fill the rest with '\0' bytes buffer[n] = '\0'; + input_data_pending = bool(buffer[0] != '\0'); if ( key == 0 ) // Ctrl+Space or Ctrl+@ @@ -664,8 +692,10 @@ FString FTerm::getKeyName(int keynum) for (int i=0; FkeyName[i].string[0] != 0; i++) if ( FkeyName[i].num && FkeyName[i].num == keynum ) return FString(FkeyName[i].string); + if ( keynum > 32 && keynum < 127 ) return FString(char(keynum)); + return FString(""); } @@ -683,6 +713,7 @@ void FTerm::init_console() getUnicodeMap(); getScreenFont(); } + getTermSize(); closeConsole(); } @@ -728,6 +759,7 @@ void FTerm::init_consoleCharMap() for (int i=0; i <= lastCharItem; i++ ) { bool found = false; + for (uInt n=0; n < screenUnicodeMap.entry_ct; n++) { if ( character[i][fc::UTF8] == screenUnicodeMap.entries[n].unicode ) @@ -736,6 +768,7 @@ void FTerm::init_consoleCharMap() break; } } + if ( ! found ) character[i][fc::PC] = character[i][fc::ASCII]; } @@ -787,14 +820,19 @@ char* FTerm::init_256colorTerminal() if ( s1 != 0 ) strncat (local256, s1, sizeof(local256) - strlen(local256) - 1); + if ( s2 != 0 ) strncat (local256, s2, sizeof(local256) - strlen(local256) - 1); + if ( s3 != 0 ) strncat (local256, s3, sizeof(local256) - strlen(local256) - 1); + if ( s4 != 0 ) strncat (local256, s4, sizeof(local256) - strlen(local256) - 1); + if ( s5 != 0 ) strncat (local256, s5, sizeof(local256) - strlen(local256) - 1); + if ( s6 != 0 ) strncat (local256, s6, sizeof(local256) - strlen(local256) - 1); @@ -807,8 +845,8 @@ char* FTerm::init_256colorTerminal() { new_termtype = const_cast("screen-256color"); screen_terminal = true; - char* tmux = getenv("TMUX"); + if ( tmux && strlen(tmux) != 0 ) tmux_terminal = true; } @@ -821,6 +859,7 @@ char* FTerm::init_256colorTerminal() new_termtype = const_cast("mlterm-256color"); mlterm_terminal = true; } + if ( strncmp(termtype, "rxvt", 4) != 0 && s1 && strncmp(s1, "rxvt-xpm", 8) == 0 ) @@ -828,6 +867,7 @@ char* FTerm::init_256colorTerminal() new_termtype = const_cast("rxvt-256color"); rxvt_terminal = true; } + color256 = true; } else if ( strstr (termtype, "256color") ) @@ -844,6 +884,7 @@ char* FTerm::init_256colorTerminal() new_termtype = const_cast("gnome-256color"); else new_termtype = const_cast("gnome"); + gnome_terminal = true; } @@ -861,6 +902,7 @@ char* FTerm::parseAnswerbackMsg (char*& current_termtype) if ( AnswerBack && *AnswerBack == FString("PuTTY") ) { putty_terminal = true; + if ( color256 ) new_termtype = const_cast("putty-256color"); else @@ -954,6 +996,7 @@ char* FTerm::parseSecDA (char*& current_termtype) else if ( terminal_id_version > 1000 ) { gnome_terminal = true; // vte / gnome terminal + if ( color256 ) new_termtype = const_cast("gnome-256color"); else @@ -981,6 +1024,7 @@ char* FTerm::parseSecDA (char*& current_termtype) 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 ) new_termtype = const_cast("rxvt-16color"); @@ -989,6 +1033,7 @@ char* FTerm::parseSecDA (char*& current_termtype) case 85: // rxvt-unicode rxvt_terminal = true; urxvt_terminal = true; + if ( strncmp(termtype, "rxvt-", 5) != 0 ) { if ( color256 ) @@ -1100,6 +1145,7 @@ void FTerm::init_pc_charset() tcap[t_enter_pc_charset_mode].string = \ const_cast(ESC "(U"); } + opti_attr->set_enter_pc_charset_mode (tcap[t_enter_pc_charset_mode].string); reinit = true; } @@ -1119,6 +1165,7 @@ void FTerm::init_pc_charset() tcap[t_enter_pc_charset_mode].string = \ const_cast(ESC "(B"); } + opti_attr->set_exit_pc_charset_mode (tcap[t_exit_pc_charset_mode].string); reinit = true; } @@ -1186,6 +1233,7 @@ void FTerm::init_termcaps() // gnome-terminal has NC=16 however, it can use the dim attribute if ( gnome_terminal ) attr_without_color = 0; + // PuTTY has NC=22 however, it can show underline and reverse if ( putty_terminal ) attr_without_color = 16; @@ -1391,6 +1439,7 @@ void FTerm::init_termcaps() // http://www.unix.com/shell-programming-scripting/.. // ..110380-using-arrow-keys-shell-scripts.html key_up_string = tgetstr(const_cast("ku"), &buffer); + if ( (key_up_string && (strcmp(key_up_string, CSI "A") == 0)) || ( tcap[t_cursor_up].string && (strcmp(tcap[t_cursor_up].string, CSI "A") == 0)) ) @@ -1492,10 +1541,13 @@ void FTerm::init_termcaps() opti_attr->set_orig_pair (tcap[t_orig_pair].string); opti_attr->set_orig_orig_colors (tcap[t_orig_colors].string); opti_attr->setMaxColor (max_color); + if ( ansi_default_color ) opti_attr->setDefaultColorSupport(); + if ( cygwin_terminal ) opti_attr->setCygwinTerminal(); + opti_attr->init(); } @@ -1755,13 +1807,16 @@ void FTerm::init() else { locale_name = getenv("LC_ALL"); + if ( ! locale_name ) { locale_name = getenv("LC_CTYPE"); + if ( ! locale_name ) locale_name = getenv("LANG"); } } + // Fallback to C if ( ! locale_name ) locale_name = const_cast("C"); @@ -1812,8 +1867,10 @@ void FTerm::init() setXTermCursorStyle(fc::blinking_underline); setXTermMouseBackground("rgb:ffff/ffff/ffff"); setXTermMouseForeground ("rgb:0000/0000/0000"); + if ( ! gnome_terminal ) setXTermCursorColor("rgb:ffff/ffff/ffff"); + if ( ! mintty_terminal && ! rxvt_terminal && ! screen_terminal ) { // mintty and rxvt can't reset these settings @@ -1848,6 +1905,7 @@ void FTerm::init() if ( isConsole() ) if ( setLightBackgroundColors(true) != 0 ) max_color = 8; + closeConsole(); setConsoleCursor(fc::underscore_cursor); } @@ -2015,22 +2073,29 @@ void FTerm::finish() { if ( screenFont.data != 0 ) delete[] screenFont.data; + if ( screenUnicodeMap.entries != 0 ) delete[] screenUnicodeMap.entries; } if ( encoding_set ) delete encoding_set; + if ( vt100_alt_char ) delete vt100_alt_char; + if ( output_buffer ) delete output_buffer; + if ( Sec_DA ) delete Sec_DA; + if ( AnswerBack ) delete AnswerBack; + if ( xterm_title ) delete xterm_title; + if ( xterm_font ) delete xterm_font; @@ -2038,10 +2103,13 @@ void FTerm::finish() { if ( vdesktop->changes != 0 ) delete[] vdesktop->changes; + if ( vdesktop->text != 0 ) delete[] vdesktop->text; + delete vdesktop; } + if ( vterm != 0 ) { if ( vterm->changes != 0 ) @@ -2049,11 +2117,13 @@ void FTerm::finish() delete[] vterm->changes; vterm->changes = 0; } + if ( vterm->text != 0 ) { delete[] vterm->text; vterm->text = 0; } + delete vterm; } } @@ -2075,6 +2145,7 @@ uInt FTerm::charEncode (uInt c, fc::encoding enc) break; } } + return c; } @@ -2091,6 +2162,7 @@ uInt FTerm::cp437_to_unicode (uChar c) break; } } + return ucs; } @@ -2099,7 +2171,6 @@ uInt FTerm::cp437_to_unicode (uChar c) bool FTerm::charEncodable (uInt c) { uInt ch = charEncode(c); - return bool(ch > 0 && ch != c); } @@ -2214,19 +2285,25 @@ void FTerm::restoreVTerm (int x, int y, int w, int h) 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; @@ -2248,15 +2325,18 @@ void FTerm::restoreVTerm (int x, int y, int w, int h) while ( iter != end ) { const FRect& geometry = (*iter)->getGeometryGlobalShadow(); + if ( geometry.contains(x+tx+1, y+ty+1) ) { int win_x = (*iter)->getGlobalX() - 1; int win_y = (*iter)->getGlobalY() - 1; term_area* win = (*iter)->getVWin(); int line_len = win->width + win->right_shadow; + if ( win->visible ) sc = &win->text[(y+ty-win_y) * line_len + (x+tx-win_x)]; } + ++iter; } } @@ -2270,6 +2350,7 @@ void FTerm::restoreVTerm (int x, int y, int w, int h) { int bar_x = menubar->getGlobalX() - 1; int bar_y = menubar->getGlobalY() - 1; + if ( vmenubar->visible ) sc = &vmenubar->text[(y+ty-bar_y) * vmenubar->width + (x+tx-bar_x)]; } @@ -2283,6 +2364,7 @@ void FTerm::restoreVTerm (int x, int y, int w, int h) { int bar_x = statusbar->getGlobalX() - 1; int bar_y = statusbar->getGlobalY() - 1; + if ( vstatusbar->visible ) sc = &vstatusbar->text[(y+ty-bar_y) * vstatusbar->width + (x+tx-bar_x)]; } @@ -2291,6 +2373,7 @@ void FTerm::restoreVTerm (int x, int y, int w, int h) 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); } @@ -2322,6 +2405,7 @@ bool FTerm::isCovered(int x, int y, FTerm::term_area* area) const while ( iter != end ) { const FRect& geometry = (*iter)->getGeometryGlobalShadow(); + if ( found && (*iter)->isVisible() && (*iter)->isShown() @@ -2330,14 +2414,17 @@ bool FTerm::isCovered(int x, int y, FTerm::term_area* area) const covered = true; break; } + if ( area == (*iter)->getVWin() ) found = true; + ++iter; } } // menubar is always on top FWidget* menubar; + if ( vmenubar ) menubar = reinterpret_cast(vmenubar->widget); else @@ -2351,6 +2438,7 @@ bool FTerm::isCovered(int x, int y, FTerm::term_area* area) const // statusbar is always on top FWidget* statusbar; + if ( vstatusbar ) statusbar = reinterpret_cast(vstatusbar->widget); else @@ -2398,6 +2486,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) ol = abs(ax); ax = 0; } + if ( ah + bsh + ay > vterm->height ) y_end = vterm->height - ay; else @@ -2407,12 +2496,14 @@ void FTerm::updateVTerm (FTerm::term_area* area) { 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; @@ -2422,13 +2513,13 @@ void FTerm::updateVTerm (FTerm::term_area* area) for (register int x=line_xmin; x <= line_xmax; x++) { int gx, gy, line_len; - gx = ax + x; // global position gy = ay + y; + if ( gx < 0 || gy < 0 ) continue; - line_len = aw + rsh; + line_len = aw + rsh; ac = &area->text[y * line_len + x]; tc = &vterm->text[gy * vterm->width + gx - ol]; @@ -2440,12 +2531,16 @@ void FTerm::updateVTerm (FTerm::term_area* area) 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 > 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; } @@ -2456,6 +2551,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) void FTerm::setUpdateVTerm (bool on) { vterm_updates = on; + if ( on ) updateVTerm (last_area); } @@ -2470,6 +2566,7 @@ void FTerm::getArea (int ax, int ay, FTerm::term_area* area) if ( ! area ) return; + ax--; ay--; @@ -2491,6 +2588,7 @@ void FTerm::getArea (int ax, int ay, FTerm::term_area* area) 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); } @@ -2521,6 +2619,7 @@ void FTerm::getArea (int x, int y, int w, int h, FTerm::term_area* area) length = vterm->width - x + 1; else length = w; + if ( length < 1 ) return; @@ -2529,11 +2628,11 @@ void FTerm::getArea (int x, int y, int w, int h, FTerm::term_area* area) 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]; - 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); } @@ -2544,8 +2643,10 @@ void FTerm::putArea (const FPoint& pos, FTerm::term_area* area) { if ( ! area ) return; + if ( ! area->visible ) return; + putArea (pos.getX(), pos.getY(), area); } @@ -2558,6 +2659,7 @@ void FTerm::putArea (int ax, int ay, FTerm::term_area* area) if ( ! area ) return; + if ( ! area->visible ) return; @@ -2595,14 +2697,13 @@ void FTerm::putArea (int ax, int ay, FTerm::term_area* area) for (int y=0; y < y_end; y++) { int line_len = aw + rsh; - tc = &vterm->text[(ay+y) * vterm->width + ax]; ac = &area->text[y * line_len + ol]; - memcpy (tc, ac, sizeof(FOptiAttr::char_data) * unsigned(length)); 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); } @@ -2622,11 +2723,13 @@ FOptiAttr::char_data FTerm::getCoveredCharacter (int x, int y, FTerm* obj) 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; @@ -2637,7 +2740,6 @@ FOptiAttr::char_data FTerm::getCoveredCharacter (int x, int y, FTerm* obj) { FWidget::widgetList::const_iterator iter, end; int layer = FWindow::getWindowLayer(w); - iter = w->window_list->begin(); end = w->window_list->end(); @@ -2646,6 +2748,7 @@ FOptiAttr::char_data FTerm::getCoveredCharacter (int x, int y, FTerm* obj) if ( obj && *iter != obj && layer >= FWindow::getWindowLayer(*iter) ) { const FRect& geometry = (*iter)->getGeometryGlobalShadow(); + if ( geometry.contains(x+1,y+1) ) { int win_x = (*iter)->getGlobalX() - 1; @@ -2658,6 +2761,7 @@ FOptiAttr::char_data FTerm::getCoveredCharacter (int x, int y, FTerm* obj) } else break; + ++iter; } } @@ -2685,6 +2789,7 @@ bool FTerm::setVGAFont() NewFont = false; pc_charset_console = true; Encoding = fc::PC; + if ( xterm && utf8_console ) Fputchar = &FTerm::putchar_UTF8; else @@ -2698,8 +2803,10 @@ bool FTerm::setVGAFont() { // standard vga font 8x16 int ret = setScreenFont(__8x16std, 256, 8, 16); + if ( ret != 0 ) VGAFont = false; + // unicode character mapping struct unimapdesc unimap; unimap.entry_ct = uChar ( sizeof(unicode_cp437_pairs) @@ -2709,6 +2816,7 @@ bool FTerm::setVGAFont() } else VGAFont = false; + getTermSize(); closeConsole(); } @@ -2741,6 +2849,7 @@ bool FTerm::setNewFont() fflush(stdout); pc_charset_console = true; Encoding = fc::PC; + if ( xterm && utf8_console ) Fputchar = &FTerm::putchar_UTF8; else @@ -2759,17 +2868,21 @@ bool FTerm::setNewFont() // Set the graphical font 8x16 ret = setScreenFont(__8x16graph, 256, 8, 16); + if ( ret != 0 ) NewFont = false; + // unicode character mapping unimap.entry_ct = uInt16 ( sizeof(unicode_cp437_pairs) / sizeof(unipair) ); unimap.entries = &unicode_cp437_pairs[0]; setUnicodeMap(&unimap); } + getTermSize(); closeConsole(); } + pc_charset_console = true; Encoding = fc::PC; Fputchar = &FTerm::putchar_ASCII; // function pointer @@ -2808,6 +2921,7 @@ bool FTerm::setOldFont() putstring (OSC "50;vga" BEL); oscPostfix(); } + fflush(stdout); retval = true; } @@ -2825,19 +2939,24 @@ bool FTerm::setOldFont() , screenFont.height , true ); delete[] screenFont.data; + if ( ret == 0 ) retval = true; } + if ( screenUnicodeMap.entries ) { setUnicodeMap (&screenUnicodeMap); delete[] screenUnicodeMap.entries; } + } + getTermSize(); closeConsole(); } } + return retval; } @@ -2848,8 +2967,10 @@ void FTerm::setConsoleCursor (fc::console_cursor_style style) if ( linux_terminal ) { consoleCursorStyle = style; + if ( hiddenCursor ) return; + putstringf (CSI "?%dc", style); fflush(stdout); } @@ -2930,6 +3051,7 @@ void FTerm::resizeVTerm() delete[] vterm->changes; vterm->changes = 0; } + if ( vterm->text != 0 ) { delete[] vterm->text; @@ -2946,6 +3068,7 @@ void FTerm::resizeVTerm() delete[] vterm->text; vterm->text = 0; } + vterm->text = new FOptiAttr::char_data[vterm_size]; } else @@ -2972,10 +3095,8 @@ void FTerm::resizeVTerm() default_char.pc_charset = 0; std::fill_n (vterm->text, vterm_size, default_char); - unchanged.xmin = uInt(term_width); unchanged.xmax = 0; - std::fill_n (vterm->changes, term_height, unchanged); } @@ -2987,6 +3108,7 @@ void FTerm::putVTerm() vterm->changes[i].xmin = 0; vterm->changes[i].xmax = uInt(vterm->width - 1); } + updateTerminal(); } @@ -3021,6 +3143,7 @@ void FTerm::updateTerminal() 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; @@ -3041,9 +3164,11 @@ void FTerm::updateTerminal() x_term_pos++; } + vt->changes[y].xmin = uInt(vt->width); vt->changes[y].xmax = 0; } + // cursor wrap if ( x_term_pos > term_width ) { @@ -3076,6 +3201,7 @@ void FTerm::updateTerminal() && focus_widget->isCursorInside() ) { focus_widget->setCursor(); + if ( focus_widget->hasVisibleCursor() ) showCursor(); } @@ -3085,6 +3211,7 @@ void FTerm::updateTerminal() void FTerm::updateTerminal (bool on) { stop_terminal_updates = bool(! on); + if ( on ) updateTerminal(); } @@ -3106,6 +3233,7 @@ void FTerm::setKDECursor (fc::kde_konsole_CursorShape style) FString FTerm::getXTermFont() { FString font(""); + if ( xterm || screen_terminal || osc_support ) { if ( raw_mode && non_blocking_stdin ) @@ -3129,6 +3257,7 @@ FString FTerm::getXTermFont() } } } + return font; } @@ -3158,6 +3287,7 @@ FString FTerm::getXTermTitle() title = static_cast(temp + 3); } } + return title; } @@ -3399,6 +3529,7 @@ void FTerm::resetColorMap() } ioctl (0, PIO_CMAP, &map); }*/ + fflush(stdout); } @@ -3423,6 +3554,7 @@ void FTerm::setPalette (short index, int r, int g, int b) color_str = tparm(Ic, index, rr, gg, bb, 0, 0, 0, 0, 0); else if ( Ip ) color_str = tparm(Ip, index, 0, 0, 0, rr, gg, bb, 0, 0); + putstring (color_str); } else if ( linux_terminal ) @@ -3438,6 +3570,7 @@ void FTerm::setPalette (short index, int r, int g, int b) } ioctl (0, PIO_CMAP, &map); */ } + fflush(stdout); } @@ -3447,6 +3580,7 @@ void FTerm::xtermMouse (bool on) // activate/deactivate the xterm mouse support if ( ! mouse_support ) return; + if ( on ) putstring (CSI "?1001s" // save old highlight mouse tracking CSI "?1000h" // enable x11 mouse tracking @@ -3459,6 +3593,7 @@ void FTerm::xtermMouse (bool on) CSI "?1002l" // disable cell motion mouse tracking CSI "?1000l" // disable x11 mouse tracking CSI "?1001r"); // restore old highlight mouse tracking + fflush(stdout); } @@ -3475,6 +3610,7 @@ bool FTerm::gpmMouse (bool on) { if ( ! isConsole() ) return false; + closeConsole(); } @@ -3485,8 +3621,8 @@ bool FTerm::gpmMouse (bool on) conn.defaultMask = GPM_MOVE; conn.maxMod = uInt16(~0); conn.minMod = 0; - Gpm_Open(&conn, 0); + switch ( gpm_fd ) { case -1: @@ -3504,6 +3640,7 @@ bool FTerm::gpmMouse (bool on) { Gpm_Close(); } + return on; } #endif // F_HAVE_LIBGPM @@ -3542,7 +3679,6 @@ void FTerm::setTermXY (register int x, register int y) appendOutputBuffer(move_str); flush_out(); - x_term_pos = x; y_term_pos = y; } @@ -3552,12 +3688,15 @@ void FTerm::setBeep (int Hz, int ms) { if ( ! linux_terminal ) return; + // range for frequency: 21-32766 if ( Hz < 21 || Hz > 32766 ) return; + // range for duration: 0-1999 if ( ms < 0 || ms > 1999 ) return; + putstringf ( CSI "10;%d]" CSI "11;%d]" , Hz, ms ); @@ -3569,6 +3708,7 @@ void FTerm::resetBeep() { if ( ! linux_terminal ) return; + // default frequency: 750 Hz // default duration: 125 ms putstring ( CSI "10;750]" @@ -3610,6 +3750,7 @@ bool FTerm::hideCursor (bool on) appendOutputBuffer (ve); else if ( vs ) appendOutputBuffer (vs); + hiddenCursor = false; } flush_out(); @@ -3681,6 +3822,7 @@ std::string FTerm::getEncoding() for (it = encoding_set->begin(); it != end; ++it ) if ( it->second == Encoding ) return it->first; + return ""; } @@ -3693,15 +3835,18 @@ bool FTerm::setNonBlockingInput (bool on) if ( on ) // make stdin non-blocking { stdin_status_flags |= O_NONBLOCK; + if ( fcntl (stdin_no, F_SETFL, stdin_status_flags) != -1 ) non_blocking_stdin = true; } else { stdin_status_flags &= ~O_NONBLOCK; + if ( fcntl (stdin_no, F_SETFL, stdin_status_flags) != -1 ) non_blocking_stdin = false; } + return non_blocking_stdin; } @@ -3723,6 +3868,7 @@ bool FTerm::setUTF8 (bool on) // UTF-8 (Unicode) else putstring (ESC "%@"); } + fflush(stdout); return utf8_state; } @@ -3775,6 +3921,7 @@ bool FTerm::setRawMode (bool on) tcsetattr (stdin_no, TCSAFLUSH, &term_init); raw_mode = false; } + return raw_mode; } @@ -3810,6 +3957,7 @@ FString FTerm::getAnswerbackMsg() } } } + return answerback; } @@ -3851,6 +3999,7 @@ FString FTerm::getSecDA() } } } + return sec_da; } @@ -3967,7 +4116,6 @@ int FTerm::print (FTerm::term_area* area, const std::string& s) int FTerm::print (FString& s) { assert ( ! s.isNull() ); - term_area* area; FWidget* w; w = static_cast(this); @@ -3977,9 +4125,11 @@ int FTerm::print (FString& s) { FWidget* area_widget = w->getRootWidget(); area = vdesktop; + if ( ! area_widget ) return -1; } + return print (area, s); } @@ -3993,7 +4143,9 @@ int FTerm::print (FTerm::term_area* area, FString& s) if ( ! area ) return -1; + area_widget = area->widget; + if ( ! area_widget ) return -1; @@ -4071,13 +4223,16 @@ int FTerm::print (FTerm::term_area* area, FString& s) 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 = area_widget->getGeometryGlobal(); @@ -4087,16 +4242,20 @@ int FTerm::print (FTerm::term_area* area, FString& s) cursor->x_ref() = short(area_widget->getGlobalX()); cursor->y_ref()++; } + if ( cursor->y_ref() > area_geometry.getY2()+bsh ) { cursor->y_ref()--; break; } + p++; len++; } // end of while + updateVTerm (area); } + return len; } @@ -4112,9 +4271,11 @@ int FTerm::print (register int c) { FWidget* area_widget = w->getRootWidget(); area = vdesktop; + if ( ! area_widget ) return -1; } + return print (area, c); } @@ -4148,8 +4309,8 @@ int FTerm::print (FTerm::term_area* area, register int c) x = short(cursor->getX()); y = short(cursor->getY()); - area_widget = area->widget; + if ( ! area_widget ) return -1; @@ -4170,12 +4331,13 @@ int FTerm::print (FTerm::term_area* area, register int c) 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()++; + cursor->x_ref()++; rsh = area->right_shadow; bsh = area->bottom_shadow; const FRect& area_geometry = area_widget->getGeometryGlobal(); @@ -4185,12 +4347,14 @@ int FTerm::print (FTerm::term_area* area, register int c) cursor->x_ref() = short(area_widget->getGlobalX()); cursor->y_ref()++; } + if ( cursor->y_ref() > area_geometry.getY2()+bsh ) { cursor->y_ref()--; updateVTerm (area); return -1; } + updateVTerm (area); return 1; } @@ -4252,6 +4416,7 @@ inline void FTerm::charsetChanges (FOptiAttr::char_data*& next_char) next_char->code = int(charEncode(code, fc::ASCII)); return; } + next_char->code = int(ch); if ( Encoding == fc::VT100 ) @@ -4332,18 +4497,22 @@ int FTerm::appendLowerRight (FOptiAttr::char_data*& screen_char) { 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; } @@ -4364,8 +4533,10 @@ inline void FTerm::appendOutputBuffer (const char* s) int FTerm::appendOutputBuffer (int ch) { output_buffer->push(ch); + if ( output_buffer->size() >= 2048 ) flush_out(); + return ch; } @@ -4377,6 +4548,7 @@ void FTerm::flush_out() Fputchar (output_buffer->front()); output_buffer->pop(); } + fflush(stdout); } @@ -4488,5 +4660,6 @@ int FTerm::UTF8decode(char* utf8) ucs = EOF; } } + return ucs; } diff --git a/src/fterm.h b/src/fterm.h index 1ae7ddbf..ad2b192d 100644 --- a/src/fterm.h +++ b/src/fterm.h @@ -461,6 +461,7 @@ inline int FTerm::getLineNumber() { if ( term->getHeight() == 0 ) getTermSize(); + return term->getHeight(); } @@ -469,6 +470,7 @@ inline int FTerm::getColumnNumber() { if ( term->getWidth() == 0 ) getTermSize(); + return term->getWidth(); } diff --git a/src/ftextview.cpp b/src/ftextview.cpp index 800763ea..590b2e14 100644 --- a/src/ftextview.cpp +++ b/src/ftextview.cpp @@ -67,24 +67,30 @@ void FTextView::draw() { setUpdateVTerm(false); setColor (foregroundColor, backgroundColor); + if ( isMonochron() ) setReverse(true); + if ( ! isNewFont() ) drawBorder(); + if ( isMonochron() ) setReverse(false); + if ( VBar->isVisible() ) VBar->redraw(); + if ( HBar->isVisible() ) HBar->redraw(); - setUpdateVTerm(true); + setUpdateVTerm(true); drawText(); if ( hasFocus() && statusBar() ) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) { setUpdateVTerm(false); @@ -93,6 +99,7 @@ void FTextView::draw() setUpdateVTerm(true); } } + setCursorPos(1,1); updateTerminal(); flush_out(); @@ -105,8 +112,10 @@ void FTextView::drawText() if ( data.empty() || height < 4 || width < 5 ) return; + start = 0; end = uInt(height+nf_offset-2); + if ( end > getRows() ) end = getRows(); @@ -118,12 +127,14 @@ void FTextView::drawText() for (uInt y=start; y < end; y++) { + uInt i, len; + FString line; + const wchar_t* line_str; gotoxy (xpos+xmin, ypos+ymin-nf_offset+int(y)); - uInt i; - FString line = data[y+uInt(yoffset)].mid ( uInt(1 + xoffset) - , uInt(width - nf_offset - 2) ); - const wchar_t* line_str = line.wc_str(); - uInt len = line.getLength(); + line = data[y+uInt(yoffset)].mid ( uInt(1 + xoffset) + , uInt(width - nf_offset - 2) ); + line_str = line.wc_str(); + len = line.getLength(); for (i=0; i < len; i++) { @@ -140,6 +151,7 @@ void FTextView::drawText() else print ('.'); } + for (; i < uInt(width - nf_offset - 2); i++) print (' '); } @@ -195,11 +207,9 @@ void FTextView::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); - n = isNewFont() ? 1 : 0; size = width + n; blank = new char[size+1]; @@ -211,6 +221,7 @@ void FTextView::hide() gotoxy (xpos+xmin-1, ypos+ymin-1+y); print (blank); } + delete[] blank; flush_out(); } @@ -226,41 +237,50 @@ void FTextView::onKeyPress (FKeyEvent* ev) case fc::Fkey_up: if ( yoffset > 0 ) yoffset--; + ev->accept(); break; case fc::Fkey_down: if ( yoffset + height + nf_offset <= last_line + 1 ) yoffset++; + ev->accept(); break; case fc::Fkey_right: if ( xoffset + width - nf_offset <= int(maxLineWidth) + 1 ) xoffset++; + ev->accept(); break; case fc::Fkey_left: if ( xoffset > 0 ) xoffset--; + ev->accept(); break; case fc::Fkey_ppage: yoffset -= height-2; + if ( yoffset < 0 ) yoffset = 0; + ev->accept(); break; case fc::Fkey_npage: if ( last_line >= height ) yoffset += height-2; + if ( yoffset > last_line - height - nf_offset + 2 ) yoffset = last_line - height - nf_offset + 2; + if ( yoffset < 0 ) yoffset = 0; + ev->accept(); break; @@ -272,6 +292,7 @@ void FTextView::onKeyPress (FKeyEvent* ev) case fc::Fkey_end: if ( last_line >= height ) yoffset = last_line - height - nf_offset + 2; + ev->accept(); break; @@ -285,11 +306,15 @@ void FTextView::onKeyPress (FKeyEvent* ev) drawText(); VBar->setValue (yoffset); + if ( VBar->isVisible() ) VBar->drawBar(); + HBar->setValue (xoffset); + if ( HBar->isVisible() ) HBar->drawBar(); + updateTerminal(); flush_out(); } @@ -307,8 +332,10 @@ void FTextView::onMouseDown (FMouseEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + if ( statusBar() ) statusBar()->drawMessage(); } @@ -325,19 +352,26 @@ void FTextView::onWheel (FWheelEvent* ev) case fc::WheelUp: if ( yoffset == 0 ) break; + yoffset -= 4; + if ( yoffset < 0 ) yoffset=0; + break; case fc::WheelDown: { int yoffset_end = last_line - height - nf_offset + 2; + if ( yoffset_end < 0 ) yoffset_end = 0; + if ( yoffset == yoffset_end ) break; + yoffset += 4; + if ( yoffset > yoffset_end ) yoffset = yoffset_end; } @@ -351,11 +385,15 @@ void FTextView::onWheel (FWheelEvent* ev) drawText(); VBar->setValue (yoffset); + if ( VBar->isVisible() ) VBar->drawBar(); + HBar->setValue (xoffset); + if ( HBar->isVisible() ) HBar->drawBar(); + updateTerminal(); } @@ -391,8 +429,10 @@ void FTextView::cb_VBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepBackward: yoffset -= distance; + if ( yoffset < 0 ) yoffset = 0; + break; case FScrollbar::scrollPageForward: @@ -400,20 +440,27 @@ void FTextView::cb_VBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepForward: yoffset += distance; + if ( yoffset > last_line - height - nf_offset + 2 ) yoffset = last_line - height - nf_offset + 2; + break; case FScrollbar::scrollJump: { int val = VBar->getValue(); + if ( yoffset == val ) break; + yoffset = val; + if ( yoffset > last_line - height - nf_offset + 2 ) yoffset = last_line - height - nf_offset + 2; + if ( yoffset < 0 ) yoffset = 0; + break; } @@ -445,8 +492,10 @@ void FTextView::cb_VBarChange (FWidget*, void*) && scrollType <= FScrollbar::scrollPageForward ) { VBar->setValue (yoffset); + if ( VBar->isVisible() && yoffset_before != yoffset ) VBar->drawBar(); + updateTerminal(); } } @@ -466,8 +515,10 @@ void FTextView::cb_HBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepBackward: xoffset -= distance; + if ( xoffset < 0 ) xoffset = 0; + break; case FScrollbar::scrollPageForward: @@ -475,39 +526,53 @@ void FTextView::cb_HBarChange (FWidget*, void*) // fall through case FScrollbar::scrollStepForward: xoffset += distance; + if ( xoffset > int(maxLineWidth) - width + nf_offset + 4 ) xoffset = int(maxLineWidth) - width + nf_offset + 4; + if ( xoffset < 0 ) xoffset = 0; + break; case FScrollbar::scrollJump: { int val = HBar->getValue(); + if ( xoffset == val ) break; + xoffset = val; + if ( xoffset > int(maxLineWidth) - width + nf_offset + 4 ) xoffset = int(maxLineWidth) - width + nf_offset + 4; + if ( xoffset < 0 ) xoffset = 0; + break; } case FScrollbar::scrollWheelUp: if ( xoffset == 0 ) break; + xoffset -= 4; + if ( xoffset < 0 ) xoffset=0; + break; case FScrollbar::scrollWheelDown: if ( xoffset == xoffset_end ) break; + xoffset += 4; + if ( xoffset > xoffset_end ) xoffset = xoffset_end; + break; default: @@ -524,8 +589,10 @@ void FTextView::cb_HBarChange (FWidget*, void*) && scrollType <= FScrollbar::scrollWheelDown ) { HBar->setValue (xoffset); + if ( HBar->isVisible() && xoffset_before != xoffset ) HBar->drawBar(); + updateTerminal(); } } @@ -551,6 +618,7 @@ void FTextView::setGeometry (int x, int y, int w, int h, bool adjust) void FTextView::setPosition (int pos) { int last_line = int(getRows()); + if ( pos < 0 || pos > last_line - height + 2 ) return; @@ -560,6 +628,7 @@ void FTextView::setPosition (int pos) drawText(); VBar->setValue (yoffset); + if ( VBar->isVisible() ) VBar->drawBar(); @@ -583,14 +652,17 @@ FString FTextView::getText() const len = 0; rows = getRows(); + for (uInt i=0 ; i < rows; i++) len += data[i].getLength() + 1; FString s(len + 1); idx = 0; + for (uInt i=0 ; i < rows; i++) { const wchar_t* p = data[i].wc_str(); + if ( p ) { while ( (s[idx++] = *p++) != 0 ); @@ -601,6 +673,7 @@ FString FTextView::getText() const s[idx++] = '\n'; } } + s[idx-1] = 0; return s; } @@ -639,28 +712,34 @@ void FTextView::insert (const FString& str, int pos) .replaceControlCodes() .rtrim(); len = text_split[i].getLength(); + if ( len > maxLineWidth ) { maxLineWidth = len; + if ( len > uInt(width-nf_offset-2) ) { HBar->setMaximum (int(maxLineWidth) - width + nf_offset + 2); HBar->setPageSize (int(maxLineWidth), width - nf_offset - 2); HBar->calculateSliderValues(); + if ( ! HBar->isVisible() ) HBar->setVisible(); } } } - data.insert (iter + pos, text_split.begin(), text_split.end()); + data.insert (iter + pos, text_split.begin(), text_split.end()); VBar->setMaximum (int(getRows()) - height + 2 - nf_offset); VBar->setPageSize (int(getRows()), height - 2 + nf_offset); VBar->calculateSliderValues(); + if ( ! VBar->isVisible() && int(getRows()) >= height + nf_offset - 1 ) VBar->setVisible(); + if ( VBar->isVisible() && int(getRows()) < height + nf_offset - 1 ) VBar->hide(); + processChanged(); } @@ -671,8 +750,10 @@ void FTextView::replaceRange (const FString& str, int start, int end) if ( start > end ) return; + if ( start < 0 || start >= int(getRows()) ) return; + if ( end < 0 || end >= int(getRows()) ) return; @@ -690,7 +771,6 @@ void FTextView::clear() char* blank; data.clear(); - xoffset = 0; yoffset = 0; maxLineWidth = 0; @@ -715,6 +795,7 @@ void FTextView::clear() gotoxy (xpos+xmin, ypos+ymin-nf_offset+y); print (blank); } + delete[] blank; processChanged(); } diff --git a/src/ftogglebutton.cpp b/src/ftogglebutton.cpp index 522bd0fa..dc67f59e 100644 --- a/src/ftogglebutton.cpp +++ b/src/ftogglebutton.cpp @@ -57,8 +57,10 @@ FToggleButton::FToggleButton (const FString& txt, FWidget* parent) FToggleButton::~FToggleButton() // destructor { delAccelerator(); + if ( group() ) group()->remove(this); + if ( hasFocus() ) hideCursor(); } @@ -125,6 +127,7 @@ uChar FToggleButton::getHotkey() return 0;; } } + return 0; } @@ -153,10 +156,12 @@ void FToggleButton::setHotkeyAccelerator() void FToggleButton::draw() { bool isFocus = ((flags & fc::focus) != 0); + if ( isFocus && statusBar() ) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) { statusBar()->setMessage(msg); @@ -192,6 +197,7 @@ void FToggleButton::drawLabel() if ( ! isVisible() ) return; + if ( text.isNull() || text.isEmpty() ) return; @@ -215,8 +221,10 @@ void FToggleButton::drawLabel() i++; src++; } + *dest++ = *src++; } + if ( hotkeypos != -1 ) length--; @@ -235,11 +243,15 @@ void FToggleButton::drawLabel() if ( (z == hotkeypos) && isActive ) { setColor (wc.label_hotkey_fg, wc.label_hotkey_bg); + if ( ! isNoUnderline ) setUnderline(); + print ( LabelText[z] ); + if ( ! isNoUnderline ) unsetUnderline(); + setColor (wc.label_fg, wc.label_bg); } else @@ -351,7 +363,6 @@ void FToggleButton::hide() char* blank; FWidget::hide(); - fg = getParentWidget()->getForegroundColor(); bg = getParentWidget()->getBackgroundColor(); setColor (fg, bg); @@ -369,8 +380,10 @@ void FToggleButton::hide() void FToggleButton::setGeometry (int x, int y, int w, int h, bool adjust) { int min_width = button_width + int(text.getLength()); + if ( w < min_width ) w = min_width; + FWidget::setGeometry(x, y, w, h, adjust); } @@ -381,6 +394,7 @@ bool FToggleButton::setNoUnderline (bool on) flags |= fc::no_underline; else flags &= ~fc::no_underline; + return on; } @@ -393,6 +407,7 @@ bool FToggleButton::setEnable (bool on) { flags |= fc::active; setHotkeyAccelerator(); + if ( hasFocus() ) { foregroundColor = wc.toggle_button_active_focus_fg; @@ -411,6 +426,7 @@ bool FToggleButton::setEnable (bool on) foregroundColor = wc.toggle_button_inactive_fg; backgroundColor = wc.toggle_button_inactive_bg; } + return on; } @@ -431,7 +447,6 @@ bool FToggleButton::setFocus (bool on) foregroundColor = wc.toggle_button_active_focus_fg; backgroundColor = wc.toggle_button_active_focus_bg; - if ( isCursorInside() && (isRadioButton() || isCheckboxButton()) ) showCursor(); @@ -439,6 +454,7 @@ bool FToggleButton::setFocus (bool on) { FString msg = getStatusbarMessage(); FString curMsg = statusBar()->getMessage(); + if ( curMsg != msg ) statusBar()->setMessage(msg); } @@ -458,6 +474,7 @@ bool FToggleButton::setFocus (bool on) statusBar()->clearMessage(); } } + return on; } @@ -473,9 +490,12 @@ void FToggleButton::onMouseDown (FMouseEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); + redraw(); + if ( statusBar() ) { statusBar()->drawMessage(); @@ -522,6 +542,7 @@ void FToggleButton::onAccel (FAccelEvent* ev) FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); setFocus(); + if ( focused_widget ) focused_widget->redraw(); } @@ -539,13 +560,16 @@ void FToggleButton::onAccel (FAccelEvent* ev) checked = not checked; processToggle(); } + redraw(); + if ( statusBar() ) { statusBar()->drawMessage(); updateTerminal(); flush_out(); } + processClick(); ev->accept(); } @@ -585,10 +609,13 @@ void FToggleButton::onFocusOut (FFocusEvent* out_ev) { focus_inside_group = true; out_ev->ignore(); + if ( out_ev->getFocusType() == fc::FocusNextWidget ) group()->focusNextChild(); + if ( out_ev->getFocusType() == fc::FocusPreviousWidget ) group()->focusPrevChild(); + redraw(); } else if ( this == group()->getLastButton() @@ -616,6 +643,7 @@ bool FToggleButton::setChecked (bool on) checked = on; processToggle(); } + return checked; } @@ -624,6 +652,7 @@ void FToggleButton::setText (FString txt) { text = txt; setWidth(button_width + int(text.getLength())); + if ( isEnabled() ) { delAccelerator(); diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 543bb78e..000988d7 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -177,6 +177,7 @@ void FWidget::finish() delete close_widget; close_widget = 0; } + if ( window_list ) { delete window_list; @@ -416,6 +417,7 @@ void FWidget::adjustSize() xmax = getParentWidget()->client_xmax; ymax = getParentWidget()->client_ymax; } + xpos = widgetSize.getX(); ypos = widgetSize.getY(); width = widgetSize.getWidth(); @@ -427,6 +429,7 @@ void FWidget::adjustSize() while ( xpos+xmin-1+width > xmax+1 ) { xpos--; + if ( xpos < 1 ) { xpos = 1; @@ -437,6 +440,7 @@ void FWidget::adjustSize() while ( ypos+ymin-1+height > ymax+1 ) { ypos--; + if ( ypos < 1 ) { ypos = 1; @@ -446,18 +450,19 @@ void FWidget::adjustSize() while ( xmin+width-1 > xmax ) width--; + while ( ymin+height-1 > ymax ) height--; if ( width < 1 ) width = 1; + if ( height < 1 ) height = 1; } adjustWidgetSize.setRect(xpos, ypos, width, height); adjustWidgetSizeShadow = adjustWidgetSize + shadow; - adjustWidgetSizeGlobal.setRect ( xpos + xmin - 1 , ypos + ymin - 1 , width, height ); @@ -480,8 +485,10 @@ void FWidget::adjustSize() while ( iter != end ) { FWidget* widget = static_cast(*iter); + if ( ! widget->isWindow() ) widget->adjustSize(); + ++iter; } } @@ -521,6 +528,7 @@ void FWidget::setStatusBar (FStatusBar* sbar) { if ( ! sbar || statusbar == sbar ) return; + if ( statusbar ) delete statusbar; @@ -532,6 +540,7 @@ void FWidget::setMenuBar (FMenuBar* mbar) { if ( ! mbar || menubar == mbar ) return; + if ( menubar ) delete menubar; @@ -547,16 +556,21 @@ bool FWidget::event (FEvent* ev) { FKeyEvent* kev = static_cast(ev); bool accpt_focus = false; + if ( kev->key() == fc::Fkey_tab ) accpt_focus = focusNextChild(); else if ( kev->key() == fc::Fkey_btab ) accpt_focus = focusPrevChild(); + if ( accpt_focus ) break; + FWidget* widget = this; + while ( widget ) { widget->onKeyPress(kev); + if ( ! kev->isAccepted() ) { if ( kev->key() == fc::Fkey_right @@ -565,11 +579,14 @@ bool FWidget::event (FEvent* ev) else if ( kev->key() == fc::Fkey_left || kev->key() == fc::Fkey_up ) accpt_focus = focusPrevChild(); + if ( accpt_focus ) break; } + if ( kev->isAccepted() || widget->isRootWidget() ) break; + widget = widget->getParentWidget(); } } @@ -583,11 +600,14 @@ bool FWidget::event (FEvent* ev) { FKeyEvent* kev = static_cast(ev); FWidget* widget = this; + while ( widget ) { widget->onKeyDown(kev); + if ( kev->isAccepted() || widget->isRootWidget() ) break; + widget = widget->getParentWidget(); } } @@ -723,6 +743,7 @@ bool FWidget::focusNextChild() if ( hasParent() ) { FWidget* parent = static_cast(getParent()); + if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 ) { FObject::object_list children; @@ -735,33 +756,40 @@ bool FWidget::focusNextChild() while ( iter != end ) { FWidget* w = static_cast(*iter); + if ( w == this ) { FWidget* next; FObject::object_list::const_iterator next_element; - next_element = iter; + do { ++next_element; + if ( next_element == children.end() ) next_element = children.begin(); + next = static_cast(*next_element); } while ( ! next->isEnabled() || ! next->acceptFocus() || ! next->isVisible() || next->isWindow() ); + FFocusEvent out (fc::FocusOut_Event); out.setFocusType(fc::FocusNextWidget); FApplication::sendEvent(this, &out); + if ( out.isAccepted() ) { if ( next == this ) return false; + next->setFocus(); FFocusEvent in (fc::FocusIn_Event); in.setFocusType(fc::FocusNextWidget); FApplication::sendEvent(next, &in); + if ( in.isAccepted() ) { this->draw(); @@ -785,6 +813,7 @@ bool FWidget::focusPrevChild() if ( hasParent() ) { FWidget* parent = static_cast(getParent()); + if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 ) { FObject::object_list children; @@ -793,29 +822,34 @@ bool FWidget::focusPrevChild() children = getParent()->getChildren(); iter = children.end(); begin = children.begin(); + do { --iter; FWidget* w = static_cast(*iter); + if ( w == this ) { FWidget* prev; FObject::object_list::const_iterator prev_element; - prev_element = iter; + do { if ( prev_element == children.begin() ) prev_element = children.end(); + --prev_element; prev = static_cast(*prev_element); } while ( ! prev->isEnabled() || ! prev->acceptFocus() || ! prev->isVisible() || prev->isWindow() ); + FFocusEvent out (fc::FocusOut_Event); out.setFocusType(fc::FocusPreviousWidget); FApplication::sendEvent(this, &out); + if ( out.isAccepted() ) { if ( prev == this ) @@ -832,11 +866,14 @@ bool FWidget::focusPrevChild() flush_out(); } } + break; } - } while ( iter != begin ); + } + while ( iter != begin ); } } + return true; } @@ -885,6 +922,7 @@ FWidget* FWidget::childWidgetAt (FWidget* p, int x, int y) while ( iter != end ) { FWidget* widget = static_cast(*iter); + if ( widget->isEnabled() && widget->isVisible() && ! widget->isWindow() @@ -893,9 +931,11 @@ FWidget* FWidget::childWidgetAt (FWidget* p, int x, int y) FWidget* child = childWidgetAt(widget, x, y); return (child != 0) ? child : widget; } + ++iter; } } + return 0; } @@ -948,7 +988,6 @@ int FWidget::numOfFocusableChildren() return 0; int num = 0; - children = this->getChildren(); iter = children.begin(); end = children.end(); @@ -956,10 +995,13 @@ int FWidget::numOfFocusableChildren() while ( iter != end ) { FWidget* widget = static_cast(*iter); + if ( widget->acceptFocus() ) num++; + ++iter; } + return num; } @@ -976,6 +1018,7 @@ bool FWidget::close() else { hide(); + if ( (flags & fc::modal) == 0 ) close_widget->push_back(this); } @@ -1088,9 +1131,11 @@ void FWidget::emitCallback (FString emit_signal) // call the member function pointer (m_iter->cb_instance->*callback)(this, m_iter->data); } + ++m_iter; } } + // function pointer if ( ! callbackObjects.empty() ) { @@ -1106,6 +1151,7 @@ void FWidget::emitCallback (FString emit_signal) // call the function pointer callback(this, iter->data); } + ++iter; } } @@ -1119,8 +1165,10 @@ void FWidget::addAccelerator (int key, FWidget* obj) if ( ! window ) window = getRootWidget(); + if ( window == statusbar || window == menubar ) window = FWindow::getWindowWidget(getParentWidget()); + if ( window && window->accelerator_list ) window->accelerator_list->push_back(accel); } @@ -1132,8 +1180,10 @@ void FWidget::delAccelerator (FWidget* obj) if ( ! window ) window = getRootWidget(); + if ( window == statusbar || window == menubar ) window = FWindow::getWindowWidget(getParentWidget()); + if ( window && window->accelerator_list && ! window->accelerator_list->empty() ) @@ -1206,9 +1256,11 @@ void FWidget::redraw() (*iter)->redraw(); } + ++iter; } } + if ( menubar && vmenubar ) { int w = vmenubar->width; @@ -1216,6 +1268,7 @@ void FWidget::redraw() std::fill_n (vmenubar->text, w * h, default_char); menubar->redraw(); } + if ( statusbar && vstatusbar ) { int w = vstatusbar->width; @@ -1239,8 +1292,10 @@ void FWidget::redraw() while ( iter != end ) { FWidget* widget = static_cast(*iter); + if ( widget->isVisible() && ! widget->isWindow() ) widget->redraw(); + ++iter; } } @@ -1270,6 +1325,7 @@ void FWidget::resize() if ( menubar ) { menubar->setGeometry(1, 1, width, 1, false); + if ( vmenubar ) resizeArea(vmenubar); } @@ -1277,9 +1333,11 @@ void FWidget::resize() if ( statusbar ) { statusbar->setGeometry(1, height, width, 1, false); + if ( vstatusbar ) resizeArea(vstatusbar); } + adjustSizeGlobal(); } else @@ -1355,6 +1413,7 @@ void FWidget::hide() FWidget::setFocusWidget(getParentWidget()); } } + FHideEvent hide_ev (fc::Hide_Event); FApplication::sendEvent(this, &hide_ev); } @@ -1406,6 +1465,7 @@ bool FWidget::focusFirstChild() && ! widget->isMenu() ) { widget->setFocus(); + if ( widget->numOfChildren() >= 1 ) { if ( ! widget->focusFirstChild() && widget->isWindow() ) @@ -1414,8 +1474,10 @@ bool FWidget::focusFirstChild() continue; } } + return true; } + // prefix increment (++) is faster // than postfix for non primitive type ++iter; @@ -1446,11 +1508,13 @@ bool FWidget::focusLastChild() && ! widget->isMenu() ) { widget->setFocus(); + if ( widget->numOfChildren() >= 1 ) { if ( ! widget->focusLastChild() && widget->isWindow() ) continue; } + return true; } } @@ -1466,6 +1530,7 @@ bool FWidget::setFocus (bool on) if ( ! enable ) return false; + if ( on == focus ) return true; @@ -1493,6 +1558,7 @@ bool FWidget::setFocus (bool on) { bool has_raised = window->raiseWindow(); FWindow::setActiveWindow(window); + if ( has_raised && window->isVisible() && window->isShown() ) window->redraw(); } @@ -1799,6 +1865,7 @@ void FWidget::move (int x, int y) { if ( x == xpos && y == ypos ) return; + // Avoid to move widget completely outside the terminal if ( x+width < 1 || x > term->getWidth() || y < 1 || y > term->getHeight() ) return; @@ -1870,6 +1937,7 @@ void FWidget::clrscr() area = area_widget->getVWin(); else area = vdesktop; + if ( ! area ) return; @@ -1892,6 +1960,7 @@ void FWidget::clrscr() area->changes[i].xmin = 0; area->changes[i].xmax = uInt(area->width + area->right_shadow - 1); } + putArea (xpos+xmin-1, ypos+ymin-1, area); } @@ -1931,28 +2000,40 @@ void FWidget::drawShadow() if ( ch.bold ) setBold (true); + if ( ch.dim ) setDim (true); + if ( ch.italic ) setItalic (true); + if ( ch.underline ) setUnderline (true); + if ( ch.blink ) setBlink (true); + if ( ch.reverse ) setReverse (true); + if ( ch.standout ) setStandout (true); + if ( ch.invisible ) setInvisible (true); + if ( ch.protect ) setProtected (true); + if ( ch.crossed_out ) setCrossedOut (true); + if ( ch.dbl_underline ) setDoubleUnderline (true); + if ( ch.alt_charset ) setAltCharset (true); + if ( ch.pc_charset ) setPCcharset (true); @@ -1962,12 +2043,15 @@ void FWidget::drawShadow() } setColor (wc.shadow_bg, wc.shadow_fg); + for (int i=1; i < height && y1+i <= ymax; i++) { gotoxy (x2+1, y1+i); + for (int x=1; x <= 2; x++) { ch = getCoveredCharacter (x2+x, y1+i, this); + if ( ch.code == fc::LowerHalfBlock || ch.code == fc::UpperHalfBlock || ch.code == fc::LeftHalfBlock @@ -1979,6 +2063,7 @@ void FWidget::drawShadow() } } } + if ( y2 < ymax ) { gotoxy (x1, y2+1); @@ -1990,40 +2075,53 @@ void FWidget::drawShadow() if ( ch.bold ) setBold (true); + if ( ch.dim ) setDim (true); + if ( ch.italic ) setItalic (true); + if ( ch.underline ) setUnderline (true); + if ( ch.blink ) setBlink (true); + if ( ch.reverse ) setReverse (true); + if ( ch.standout ) setStandout (true); + if ( ch.invisible ) setInvisible (true); + if ( ch.protect ) setProtected (true); + if ( ch.crossed_out ) setCrossedOut (true); + if ( ch.dbl_underline ) setDoubleUnderline (true); + if ( ch.alt_charset ) setAltCharset (true); + if ( ch.pc_charset ) setPCcharset (true); print (ch.code); - setNormal(); } setColor (wc.shadow_bg, wc.shadow_fg); + for (int i=2; i <= width+1 && x1+i <= xmax; i++) { ch = getCoveredCharacter (x1+i, y2+1, this); + if ( ch.code == fc::LowerHalfBlock || ch.code == fc::UpperHalfBlock || ch.code == fc::LeftHalfBlock @@ -2034,6 +2132,7 @@ void FWidget::drawShadow() print (ch.code); } } + if ( isMonochron() ) setReverse(false); } @@ -2067,10 +2166,12 @@ void FWidget::drawShadow() if ( y2 < ymax ) { gotoxy (x1+1, y2+1); + for (int i=1; i <= width && x1+i <= xmax; i++) { ch = getCoveredCharacter (x1+i, y2+1, this); setColor (wc.shadow_fg, ch.bg_color); + if ( isTeraTerm() ) print (0xdf); // ▀ else @@ -2104,9 +2205,11 @@ void FWidget::clearShadow() print (' '); // clear █ } } + if ( y2 < ymax ) { gotoxy (x1+1, y2+1); + for (int i=1; i <= width && x1+i <= xmax; i++) { ch = getCoveredCharacter (x1+i, y2+1, this); @@ -2130,9 +2233,11 @@ void FWidget::drawFlatBorder() y2 = ypos+ymin-1+height; setColor (wc.dialog_fg, wc.dialog_bg); + for (int y=0; y < height; y++) { gotoxy (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) else @@ -2140,16 +2245,19 @@ void FWidget::drawFlatBorder() } gotoxy (x2, y1+1); + for (int y=0; y < height; y++) { if ( double_flatline_mask.right[uLong(y)] ) print (fc::NF_rev_border_line_right_and_left); // left+right line (on right side) else print (fc::NF_border_line_left); // left line (on right side) + gotoxy (x2, y1+y+2); } gotoxy (x1, y1); + for (int x=0; x < width; x++) { if ( double_flatline_mask.top[uLong(x)] ) @@ -2159,6 +2267,7 @@ void FWidget::drawFlatBorder() } gotoxy (x1, y2); + for (int x=0; x < width; x++) { if ( double_flatline_mask.bottom[uLong(x)] ) @@ -2278,10 +2387,13 @@ void FWidget::drawBorder() if ( x1 < xmin ) x1 = xmin; + if ( y1 < ymin ) y1 = ymin; + if ( x2 > xmax ) x2 = xmax; + if ( y2 > ymax ) y2 = ymax; @@ -2290,9 +2402,12 @@ void FWidget::drawBorder() setColor (wc.dialog_fg, wc.dialog_bg); gotoxy (x1, y1); print (fc::NF_border_corner_middle_upper_left); // ┌ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::NF_border_corner_middle_upper_right); // ┐ + for (int y=y1+1; y <= y2; y++) { gotoxy (x1, y); @@ -2300,10 +2415,13 @@ void FWidget::drawBorder() gotoxy (x2, y); print (fc::NF_rev_border_line_right); // border right⎹ } + gotoxy (x1, y2); print (fc::NF_border_corner_middle_lower_left); // └ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::NF_border_corner_middle_lower_right); // ┘ } else @@ -2313,7 +2431,9 @@ void FWidget::drawBorder() for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::BoxDrawingsDownAndLeft); // ┐ + for (int y=y1+1; y < y2; y++) { gotoxy (x1, y); @@ -2321,10 +2441,13 @@ void FWidget::drawBorder() gotoxy (x2, y); print (fc::BoxDrawingsVertical); // │ } + gotoxy (x1, y2); print (fc::BoxDrawingsUpAndRight); // └ + for (int x=x1+1; x < x2; x++) print (fc::BoxDrawingsHorizontal); // ─ + print (fc::BoxDrawingsUpAndLeft); // ┘ for (int x=x1+1; x < x2; x++) diff --git a/src/fwindow.cpp b/src/fwindow.cpp index ea9c9299..ac1ba4c3 100644 --- a/src/fwindow.cpp +++ b/src/fwindow.cpp @@ -78,8 +78,10 @@ void FWindow::onWindowLowered (FEvent*) void FWindow::show() { term_area* area = getVWin(); + if ( area ) area->visible = true; + FWidget::show(); } @@ -87,8 +89,10 @@ void FWindow::show() void FWindow::hide() { term_area* area = getVWin(); + if ( area ) area->visible = false; + FWidget::hide(); } @@ -114,13 +118,16 @@ FWindow* FWindow::getWindowWidgetAt (int x, int y) if ( *iter ) { FWindow* w = static_cast(*iter); + if ( ! w->isHiddenWindow() && w->getGeometryGlobal().contains(x,y) ) return w; } } while ( iter != begin ); + } + return 0; } @@ -148,6 +155,7 @@ void FWindow::delWindow (FWidget* obj) window_list->erase(iter); return; } + ++iter; } } @@ -158,11 +166,13 @@ FWindow* FWindow::getWindowWidget (FWidget* obj) { // returns the window object to the given widget obj FWidget* p_obj = obj->getParentWidget(); + while ( ! obj->isWindow() && p_obj ) { obj = p_obj; p_obj = p_obj->getParentWidget(); } + if ( obj->isWindow() ) return static_cast(obj); else @@ -178,6 +188,7 @@ int FWindow::getWindowLayer (FWidget* obj) if ( ! window_list ) return -1; + if ( window_list->empty() ) return -1; @@ -196,6 +207,7 @@ int FWindow::getWindowLayer (FWidget* obj) { if ( *iter == window ) break; + ++iter; } @@ -210,10 +222,13 @@ void FWindow::swapWindow (FWidget* obj1, FWidget* obj2) if ( ! window_list ) return; + if ( window_list->empty() ) return; + if ( (obj1->getFlags() & fc::modal) != 0 ) return; + if ( (obj2->getFlags() & fc::modal) != 0 ) return; @@ -228,6 +243,7 @@ void FWindow::swapWindow (FWidget* obj1, FWidget* obj2) iter1 = iter; else if ( (*iter) == obj2 ) iter2 = iter; + ++iter; } @@ -243,12 +259,16 @@ bool FWindow::raiseWindow (FWidget* obj) if ( ! window_list ) return false; + if ( window_list->empty() ) return false; + if ( ! obj->isWindow() ) return false; + if ( window_list->back() == obj ) return false; + if ( (window_list->back()->getFlags() & fc::modal) != 0 && ! obj->isMenu() ) return false; @@ -265,8 +285,10 @@ bool FWindow::raiseWindow (FWidget* obj) FApplication::sendEvent(obj, &ev); return true; } + ++iter; } + return false; } @@ -278,12 +300,16 @@ bool FWindow::lowerWindow (FWidget* obj) if ( ! window_list ) return false; + if ( window_list->empty() ) return false; + if ( ! obj->isWindow() ) return false; + if ( window_list->front() == obj ) return false; + if ( (obj->getFlags() & fc::modal) != 0 ) return false; @@ -299,8 +325,10 @@ bool FWindow::lowerWindow (FWidget* obj) FApplication::sendEvent(obj, &ev); return true; } + ++iter; } + return false; } @@ -312,6 +340,7 @@ void FWindow::setActiveWindow (FWindow* window) if ( ! window_list ) return; + if ( window_list->empty() ) return; @@ -332,6 +361,7 @@ void FWindow::setActiveWindow (FWindow* window) else { FWindow* w = static_cast(*iter); + if ( w->isActiveWindow() ) { w->deactivateWindow(); @@ -339,6 +369,7 @@ void FWindow::setActiveWindow (FWindow* window) FApplication::sendEvent(*iter, &ev); } } + ++iter; } } @@ -356,16 +387,20 @@ void FWindow::switchToPrevWindow() { // switch to previous window activatePrevWindow(); - FWindow* active_window = getActiveWindow(); + if ( active_window ) { FWidget* focus_widget = active_window->getFocusWidget(); + if ( ! active_window->isActiveWindow() ) setActiveWindow(active_window); + raiseWindow (active_window); + if ( focus_widget ) focus_widget->setFocus(); + active_window->redraw(); } } @@ -400,6 +435,7 @@ bool FWindow::isHiddenWindow() const { // returns the window hidden state term_area* area = getVWin(); + if ( area ) return ! area->visible; else diff --git a/test/calculator.cpp b/test/calculator.cpp index 04b93fb0..954b3850 100644 --- a/test/calculator.cpp +++ b/test/calculator.cpp @@ -59,6 +59,7 @@ void Button::setChecked (bool on) setFocusForegroundColor(wc.button_active_focus_fg); setFocusBackgroundColor(wc.button_active_focus_bg); } + redraw(); } } @@ -224,7 +225,6 @@ Calc::Calc (FWidget* parent) }; setlocale(LC_NUMERIC, "C"); - setText ("calculator"); setGeometry (19, 6, 37, 18); addAccelerator('q'); // press 'q' to quit @@ -245,12 +245,15 @@ Calc::Calc (FWidget* parent) y = (key+n)/5*2 + 3; btn->setGeometry(x, y, 5, 1); } + btn->setFlat(); btn->setNoUnderline(); btn->setText(button_text[key]); btn->setDoubleFlatLine(fc::top); + if ( isNewFont() ) btn->unsetClickAnimation(); + if ( key <= Three ) btn->setDoubleFlatLine(fc::bottom); @@ -311,15 +314,18 @@ void Calc::drawDispay() display = " Error "; setColor(fc::Black, fc::LightGray); + if ( isMonochron() ) setReverse(false); + gotoxy (xpos+xmin+1, ypos+ymin+1); print(display); print(L' '); - setColor(wc.dialog_fg, wc.dialog_bg); + if ( isMonochron() ) setReverse(true); + if ( isNewFont() ) { FString bottom_line(33, wchar_t(fc::NF_border_line_bottom)); @@ -346,6 +352,7 @@ void Calc::drawDispay() gotoxy (xpos+xmin-1, ypos+ymin+2); print(separator); } + setUpdateVTerm(true); } @@ -479,6 +486,7 @@ void Calc::calcInfixOperator() case '^': a = pow(a, b); + if ( errno == EDOM || errno == ERANGE ) error = true; break; @@ -505,10 +513,12 @@ void Calc::onKeyPress (FKeyEvent* ev) input = ""; else input = input.left(input.getLength() - 1); + a = atof(input.c_str()); drawDispay(); updateTerminal(); } + ev->accept(); break; @@ -568,8 +578,10 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) if ( arcus_mode ) { *x = log(*x + sqrt((*x) * (*x) + 1)); + if ( errno == EDOM || errno == ERANGE ) error = true; + if ( *x == INFINITY ) error = true; } @@ -585,8 +597,10 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) else *x = sin(*x * PI/180.0L); } + if ( errno == EDOM ) error = true; + setDisplay(*x); arcus_mode = false; hyperbolic_mode = false; @@ -600,8 +614,10 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) if ( arcus_mode ) { *x = log(*x + sqrt((*x) * (*x) - 1)); + if ( errno == EDOM || errno == ERANGE ) error = true; + if ( *x == INFINITY ) error = true; } @@ -617,8 +633,10 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) else *x = cos(*x * PI/180.0L); } + if ( errno == EDOM ) error = true; + setDisplay(*x); arcus_mode = false; hyperbolic_mode = false; @@ -633,6 +651,7 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) if ( *x < 1 ) { *x = 0.5L * log((1+(*x))/(1-(*x))); + if ( errno == EDOM || errno == ERANGE ) error = true; } @@ -655,8 +674,10 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) else *x = tan(*x * PI/180.0L); } + if ( errno == EDOM ) error = true; + setDisplay(*x); arcus_mode = false; hyperbolic_mode = false; @@ -688,50 +709,62 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) case Natural_logarithm: // ln *x = log(*x); + if ( errno == EDOM || errno == ERANGE ) error = true; + setDisplay(*x); break; case Powers_of_e: // eˣ *x = exp(*x); + if ( errno == ERANGE ) error = true; + setDisplay(*x); break; case Power: // yˣ if ( ! isOperatorKey(last_key) ) calcInfixOperator(); + setDisplay(*x); setInfixOperator('^'); break; case Square_root: // sqrt *x = sqrt(*x); + if ( errno == EDOM || errno == ERANGE ) error = true; + setDisplay(*x); break; case Divide: // ÷ if ( ! isOperatorKey(last_key) ) calcInfixOperator(); + setDisplay(a); setInfixOperator('/'); break; case Common_logarithm: // lg *x = log10(*x); + if ( errno == EDOM || errno == ERANGE ) error = true; + setDisplay(*x); break; case Powers_of_ten: // 10ˣ *x = pow(10,*x); + if ( errno == EDOM || errno == ERANGE ) error = true; + setDisplay(*x); break; @@ -762,6 +795,7 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) case Multiply: // * if ( ! isOperatorKey(last_key) ) calcInfixOperator(); + setDisplay(a); setInfixOperator('*'); break; @@ -805,6 +839,7 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) case Subtract: // - if ( ! isOperatorKey(last_key) ) calcInfixOperator(); + setDisplay(a); setInfixOperator('-'); break; @@ -848,6 +883,7 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) case Add: // + if ( ! isOperatorKey(last_key) ) calcInfixOperator(); + setDisplay(a); setInfixOperator('+'); break; @@ -942,6 +978,7 @@ void Calc::cb_buttonClicked (FWidget*, void* data_ptr) if ( infix_operator && ! isDataEntryKey(key) ) input = ""; + last_key = key; } diff --git a/test/mandelbrot.cpp b/test/mandelbrot.cpp index ff395e3d..8bc6fed5 100644 --- a/test/mandelbrot.cpp +++ b/test/mandelbrot.cpp @@ -78,12 +78,15 @@ void Mandelbrot::draw() x = xtemp; iter++; } + if ( iter < max_iter ) setColor(fc::Black, iter%16); else setColor(fc::Black, 0); + print(' '); } + current_line++; } @@ -105,6 +108,7 @@ void Mandelbrot::onClose (FCloseEvent* ev) "to quit the program ?" , FMessageBox::Yes , FMessageBox::No ); + if ( ret == FMessageBox::Yes ) ev->accept(); else diff --git a/test/menu.cpp b/test/menu.cpp index d6487ab3..939732fa 100644 --- a/test/menu.cpp +++ b/test/menu.cpp @@ -227,6 +227,7 @@ void Menu::onClose (FCloseEvent* ev) "to quit the program ?" , FMessageBox::Yes , FMessageBox::No ); + if ( ret == FMessageBox::Yes ) ev->accept(); else diff --git a/test/string-operations.cpp b/test/string-operations.cpp index 2264e120..49675fdf 100644 --- a/test/string-operations.cpp +++ b/test/string-operations.cpp @@ -15,11 +15,13 @@ int main (int, char**) // init current locale printf (" Locale: %s\n", setlocale(LC_CTYPE, "") ); + if ( isatty(1) && ! strcmp(nl_langinfo(CODESET), "ANSI_X3.4-1968") ) { // locale C -> switch from 7bit ascii -> latin1 setlocale(LC_ALL, "en_US"); } + printf (" Codeset: %s\n", nl_langinfo(CODESET)); std::cout << "--------------[ FString test ]-----------------" @@ -78,26 +80,32 @@ int main (int, char**) std::cout << " add: " << add13 << std::endl; FString cmp = "compare"; + if ( cmp == FString("compare") ) std::cout << " cmp: == Ok" << std::endl; else std::cout << " cmp: == Not Ok" << std::endl; + if ( cmp <= FString("d_compare") ) std::cout << " cmp: <= Ok" << std::endl; else std::cout << " cmp: <= Not Ok" << std::endl; + if ( cmp < FString("e_compare") ) std::cout << " cmp: < Ok" << std::endl; else std::cout << " cmp: < Not Ok" << std::endl; + if ( cmp >= FString("b_compare") ) std::cout << " cmp: >= Ok" << std::endl; else std::cout << " cmp: >= Not Ok" << std::endl; + if ( cmp > FString("a_compare") ) std::cout << " cmp: > Ok" << std::endl; else std::cout << " cmp: > Not Ok" << std::endl; + if ( cmp != FString("equal") ) std::cout << " cmp: != Ok" << std::endl; else @@ -109,8 +117,10 @@ int main (int, char**) std::vector parts = split_str.split(","); std::vector::iterator it, end; end = parts.end(); + for (it = parts.begin(); it != end; ++it) std::cout << " \"" << (*it) << "\""; + std::cout << std::endl; FString formatStr = ""; @@ -146,6 +156,7 @@ int main (int, char**) } setlocale(LC_NUMERIC, "C"); + try { double double_num = FString("2.7182818284590452353").toDouble(); @@ -207,6 +218,7 @@ int main (int, char**) << alphabet.right(11) << "\"" << std::endl; FString insert_str = "I am a string"; + try { std::cout << " insert: " @@ -219,6 +231,7 @@ int main (int, char**) FString index(5); // a string with five characters index = "index"; + try { index[0] = L'I'; // write a wide character at position 0 @@ -235,11 +248,13 @@ int main (int, char**) FString::iterator iter; iter = stringIterator.begin(); std::cout << " " << stringIterator << ": "; + while ( iter != stringIterator.end() ) { std::cout << char(*iter) << "|"; ++iter; } + std::cout << " (front='" << char(stringIterator.front()) << "', back='" << char(stringIterator.back()) << "')" << std::endl; @@ -253,6 +268,7 @@ int main (int, char**) << remove_std.remove(7,2) << std::endl; FString include_std = "string"; + if ( include_std.includes("ring") ) std::cout << " includes: \"" << include_std << "\" includes \"ring\" " @@ -261,6 +277,7 @@ int main (int, char**) std::cout << " includes: \"" << include_std << "\" includes no \"ring\" " << std::endl; + if ( include_std.includes("data") ) std::cout << " includes: \"" << include_std << "\" includes \"data\" " diff --git a/test/term-attributes.cpp b/test/term-attributes.cpp index e28ec640..578d60fb 100644 --- a/test/term-attributes.cpp +++ b/test/term-attributes.cpp @@ -65,6 +65,7 @@ AttribDlg::AttribDlg (FWidget* parent) "clicked", _METHOD_CALLBACK (this, &AttribDlg::cb_next) ); + back_button->addCallback ( "clicked", @@ -102,6 +103,7 @@ void AttribDlg::onClose (FCloseEvent* ev) "to quit the program ?" , FMessageBox::Yes , FMessageBox::No ); + if ( ret == FMessageBox::Yes ) ev->accept(); else @@ -113,9 +115,12 @@ void AttribDlg::cb_next (FWidget*, void*) { if ( isMonochron() ) return; + bgcolor++; + if ( bgcolor >= getMaxColor() ) bgcolor = fc::Default; + redraw(); } @@ -124,9 +129,12 @@ void AttribDlg::cb_back (FWidget*, void*) { if ( isMonochron() ) return; + bgcolor--; + if ( bgcolor < fc::Default ) bgcolor = short(getMaxColor() - 1); + redraw(); } @@ -135,8 +143,10 @@ void AttribDlg::adjustSize() { int x = ((getParentWidget()->getWidth() - getWidth()) / 2 ); int y = ((getParentWidget()->getHeight() - getHeight()) / 2 ) + 1; + if ( x < 1 ) x = 1; + if ( y < 1 ) y = 1; @@ -186,6 +196,7 @@ AttribDemo::AttribDemo (FWidget* parent) colors = 1; else if ( colors > 16 ) colors = 16; + unsetFocusable(); } @@ -211,6 +222,7 @@ void AttribDemo::printAltCharset() gotoxy (xpos + xmin - 1, ypos + ymin - 1); print("alternate charset: "); + if ( parent->bgcolor == fc::Default ) { setColor (fc::Default, fc::Default); @@ -222,6 +234,7 @@ void AttribDemo::printAltCharset() else setColor (fc::Black, parent->bgcolor); } + setAltCharset(); print("`abcdefghijklmnopqrstuvwxyz{|}~"); unsetAltCharset(); @@ -342,16 +355,18 @@ void AttribDemo::draw() if ( ! isMonochron() ) setColor(wc.label_fg, wc.label_bg); + gotoxy (xpos + xmin - 1, ypos + ymin + 13); short bg = static_cast(getParent())->bgcolor; print (" Background color:"); + if ( bg == fc::Default ) print (" default"); else printf ( " %d", bg); + gotoxy (xpos + xmin + 14, ypos + ymin + 15); print ("Change background color ->"); - setUpdateVTerm(true); } diff --git a/test/ui.cpp b/test/ui.cpp index cf36352b..0fcf0a24 100644 --- a/test/ui.cpp +++ b/test/ui.cpp @@ -130,8 +130,10 @@ void ProgressDialog::onTimer (FTimerEvent*) more->setEnable(); quit->setEnable(); redraw(); + if ( statusBar() ) statusBar()->drawMessage(); + updateTerminal(); flush_out(); } @@ -621,6 +623,7 @@ void MyDialog::cb_drives (FWidget*, void*) net.setGeometry (11, 4, 4, 1); FLabel cd (" CD ", &info2); cd.setGeometry (11, 6, 4, 1); + if ( isMonochron() ) { net.setReverseMode(); @@ -636,6 +639,7 @@ void MyDialog::cb_drives (FWidget*, void*) cd.setForegroundColor (fc::White); cd.setBackgroundColor (fc::DarkGray); } + info2.exec(); } } @@ -645,6 +649,7 @@ void MyDialog::cb_cutClipboard (FWidget*, void*) { if ( ! myLineEdit ) return; + clipboard = myLineEdit->getText(); myLineEdit->clearText(); myLineEdit->redraw(); @@ -655,6 +660,7 @@ void MyDialog::cb_copyClipboard (FWidget*, void*) { if ( ! myLineEdit ) return; + clipboard = myLineEdit->getText(); } @@ -663,6 +669,7 @@ void MyDialog::cb_pasteClipboard (FWidget*, void*) { if ( ! myLineEdit ) return; + myLineEdit->setText(clipboard); myLineEdit->redraw(); } @@ -672,6 +679,7 @@ void MyDialog::cb_clearInput (FWidget*, void*) { if ( ! myLineEdit ) return; + clipboard.clear(); myLineEdit->clearText(); myLineEdit->redraw(); @@ -709,9 +717,11 @@ void MyDialog::cb_updateNumber (FWidget* widget, void* data_ptr) FLabel* num = static_cast(data_ptr); int select_num = 0; uInt end = list->count(); + for (uInt n=1; n <= end; n++) if ( list->isSelected(int(n)) ) select_num++; + num->setNumber(select_num); num->redraw(); } @@ -721,10 +731,12 @@ void MyDialog::cb_activateButton (FWidget* widget, void* data_ptr) { FRadioButton* rb = static_cast(widget); FButton* button = static_cast(data_ptr); + if ( rb->isChecked() ) button->setEnable(); else button->setDisable(); + button->redraw(); } @@ -738,6 +750,7 @@ void MyDialog::cb_view (FWidget*, void* data_ptr) file = item->getText(); else file = FFileDialog::fileOpenChooser (this); + if ( file.isNull() ) return; @@ -765,13 +778,16 @@ void MyDialog::cb_view (FWidget*, void* data_ptr) std::string line = ""; std::ifstream infile; infile.open(file); + while ( ! infile.eof() && infile.good() ) { getline(infile, line); scrollText->append(line); } + if ( infile.is_open() ) infile.close(); + view->show(); } @@ -796,11 +812,15 @@ void MyDialog::adjustSize() int h = getParentWidget()->getHeight() - 4; setHeight (h, false); int X = int((getParentWidget()->getWidth() - getWidth()) / 2); + if ( X < 1 ) X = 1; + setX (X, false); + if ( myList ) myList->setHeight (getHeight() - 3, false); + FDialog::adjustSize(); }