Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

ndk++.cc

Go to the documentation of this file.
00001 // * This makes emacs happy -*-Mode: C++;-*-
00002 /****************************************************************************
00003  * Copyright (c) 2002 Fabrica de Software XXI SRL - info@lafabrica.com.ar   *
00004  * Copyright (c) 2002 RaqLink SA - info@raqlink.com                         *
00005  *                                                                          *
00006  * Permission is hereby granted, free of charge, to any person obtaining a  *
00007  * copy of this software and associated documentation files (the            *
00008  * "Software"), to deal in the Software without restriction, including      *
00009  * without limitation the rights to use, copy, modify, merge, publish,      *
00010  * distribute, distribute with modifications, sublicense, and/or sell       *
00011  * copies of the Software, and to permit persons to whom the Software is    *
00012  * furnished to do so, subject to the following conditions:                 *
00013  *                                                                          *
00014  * The above copyright notice and this permission notice shall be included  *
00015  * in all copies or substantial portions of the Software.                   *
00016  *                                                                          *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00020  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00021  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00022  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00023  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00024  *                                                                          *
00025  * Except as contained in this notice, the name(s) of the above copyright   *
00026  * holders shall not be used in advertising or otherwise to promote the     *
00027  * sale, use or other dealings in this Software without prior written       *
00028  * authorization.                                                           *
00029  ****************************************************************************/
00030 
00031 /****************************************************************************
00032  *  Author Miguel Pinkas <miguel@lafabrica.com.ar>                          *
00033  ****************************************************************************/
00034 #include "ndk++.h"
00035 
00036 using namespace std;
00037 
00038 namespace NDK_XX{
00039 
00040 ofstream logfile("NDK_debug");
00041 ofstream &get_logfile(){return logfile;}
00042 //-----------------------------------------------------------------------
00043 string DialogBox::lblOk="  OK  ";
00044 string DialogBox::lblCancel="Cancel";
00045 string DialogBox::lblYes="  Yes ";  
00046 string DialogBox::lblNo="  No  ";
00047 string DialogBox::titDataChgd="Data changed!";
00048 string DialogBox::msgAskToSave="Save before we exit?";
00049 string DialogBox:: lblApply=" Apply";
00050 
00051 
00052 /************************************************************************
00053 *   class Control                                               *
00054 ************************************************************************/
00055 //-----------------------------------------------------------------------
00056 BEGIN_FIRST_BINDINGS(Control)
00057 END_BINDINGS()
00058 
00059 
00060 ofstream &Control::send_to_log(const string &what)
00061 {
00062     logfile << what;
00063     return logfile;
00064 }
00065 
00066 
00067 //-----------------------------------------------------------------------
00068 bool Control::process_message(Control *pTarget,int what
00069                                             , int ctrl_id, void* pExtra)
00070 {
00071     if(!pTarget)
00072         return false;
00073     const BINDING_MAP* binding_map;
00074     const BINDING* pEntry;
00075 
00076     for (binding_map = pTarget->get_binding_map(); binding_map != 0;
00077       binding_map = binding_map->base_map)
00078     {
00079         assert(bindings_map != binding_map->base_map);
00080 
00081         pEntry = get_binding(binding_map->pEntries, what, ctrl_id);
00082         if (pEntry)
00083         {   
00084             if(what==0)
00085             (pTarget->*pEntry->p_cmd_fn)(); 
00086             else// found it
00087             (pTarget->*pEntry->p_notif_fn)(ctrl_id); 
00088             return true;
00089         }
00090     }
00091     return false;   // not handled
00092 }
00093 
00094 
00095 //-----------------------------------------------------------------------
00096 const BINDING* Control::get_binding(const BINDING* pEntry,int what, int ctrl_id)
00097 {
00098     // C version of search routine
00099     while (pEntry->pfn())
00100     {
00101         if (pEntry->what == what &&
00102             ctrl_id >= pEntry->ctrl_id && ctrl_id <= pEntry->last_ctrl_id){
00103             return pEntry;
00104         }
00105         pEntry++;
00106     }
00107     return 0;    // not found
00108 }
00109 
00110 
00111 //-----------------------------------------------------------------------
00112 Control::styles 
00113 Control::set_styles(Control::styles s)
00114 { 
00115     int old_style=field_style;
00116     field_style=s;
00117     return styles(old_style);
00118 }
00119     
00120 
00121 //-----------------------------------------------------------------------
00122 Control::styles 
00123 Control::set_style(Control::styles s,bool on)
00124 { 
00125     int old_style=field_style;
00126     if (on) field_style|=s;
00127     else    field_style&=~s;
00128     return styles(old_style);
00129 }  
00130 
00131 
00132 //-----------------------------------------------------------------------
00133 Control::states 
00134 Control::set_states(Control::states s)
00135 { 
00136     int old_state=field_state;
00137     field_state=s;
00138     return states(old_state);
00139 }
00140     
00141 
00142 //-----------------------------------------------------------------------
00143 Control::states 
00144 Control::set_state(Control::states s,bool on)
00145 { 
00146     int old_state=field_state;
00147     if (on) field_state|=s;
00148     else    field_state&=~s;
00149     return states(old_state);
00150 }  
00151 
00152 
00153 //-----------------------------------------------------------------------
00154 int Control::mvwin(int y, int x)
00155 {
00156     if(!is_moveable())
00157         return E_REQUEST_DENIED;
00158         
00159     int result=0;
00160     int new_x=begx()+x;
00161     int new_y=begy()+y;
00162     
00163     if( new_x > pParent->begx() 
00164         && new_x+ width() <= pParent->begx()+pParent->maxx() 
00165         && new_y > pParent->begy() 
00166         && new_y+ height() <= pParent->begy()+pParent->maxy()
00167     ){
00168         result = NCursesPanel::mvwin(new_y,new_x);
00169         if(result==OK){
00170             w->_begx = new_x;
00171             w->_begy = new_y;
00172             refresh();
00173         }
00174     }
00175     return result;
00176 }
00177 
00178         
00179 //-----------------------------------------------------------------------
00180 
00181 int Control::move_left()
00182 {
00183     int result = false;
00184     if(!arrow_is_tab())
00185         result =  true;
00186     beep();
00187     return result;
00188 }
00189 
00190 
00191 //-----------------------------------------------------------------------
00192 int Control::move_right()
00193 {
00194     int result=false;
00195     if(!arrow_is_tab())
00196         result = true;
00197     beep();
00198     return result;
00199 }
00200 
00201 
00202 //-----------------------------------------------------------------------
00203 void Control::activate()
00204 {
00205     if(is_hidden())
00206         return;
00207     top();
00208     set_state(active);
00209     if(has_frame()){
00210         attron(A_BOLD);
00211         box();
00212         attroff(A_BOLD);
00213         refresh();
00214     }
00215 }
00216 
00217 
00218 //-----------------------------------------------------------------------
00219 void Control::deactivate()
00220 {
00221     if(is_hidden())
00222         return;
00223     top();
00224     set_state(active,false);
00225     if(has_frame()){
00226         attroff(A_BOLD);
00227         box();
00228         refresh();
00229     }
00230 }
00231 
00232 
00233 /************************************************************************
00234 *   class Label                                             *
00235 ************************************************************************/
00236 //-----------------------------------------------------------------------
00237 Label::Label( Control *parent
00238                                 ,int id, const string &title
00239                                 ,int lines,int cols,int y, int x
00240                                 ,int style)
00241     : Control(parent,id,lines,cols,y,x,style)
00242         ,text(title)
00243         ,pos_x(0),pos_y(0)
00244         ,viewport(this)
00245         ,cur_x(0),cur_y(0),x_start(0)
00246 {
00247     enable_notify(false);
00248     if(has_frame()){
00249         viewport = new NCursesWindow(*this);
00250         pos_x++; 
00251         pos_y++; 
00252     }
00253     max_length = viewport->width();
00254     set_text(title);
00255     enable_notify();
00256 }
00257 
00258 
00259 //-----------------------------------------------------------------------
00260 Label::Label( int id, const string &title
00261                                 ,int lines,int cols,int y, int x
00262                                 ,int style)
00263     : Control(id,lines,cols,y,x,style)
00264         ,text(title)
00265         ,pos_x(0),pos_y(0)
00266         ,viewport(this)
00267         ,cur_x(0),cur_y(0)
00268 {
00269     enable_notify(false);
00270     if(has_frame()){
00271         viewport = new NCursesWindow(*this);
00272         pos_x++; 
00273         pos_y++; 
00274     }
00275     set_text(title);
00276     enable_notify();
00277 }
00278 
00279 
00280 //-----------------------------------------------------------------------
00281 void Label::set_text(const string &v)
00282 {
00283     string old_text= text;
00284     text = v;
00285     x_start=0;
00286     cur_x=0;
00287     refresh_text();
00288     refresh_viewport();
00289     if(old_text!=text && notify_enabled()){
00290         process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00291     }
00292 }
00293     
00294 
00295 //-----------------------------------------------------------------------
00296 int Control::driver(int key)
00297 {
00298     switch(key) {
00299         case KEY_RIGHT: 
00300             return move_right();
00301         case KEY_LEFT: 
00302             return move_left();
00303         default:                    break;
00304     }
00305     return FALSE;
00306 }
00307 
00308 
00309 //-----------------------------------------------------------------------
00310 void Label::activate()
00311 {
00312     if(is_hidden())
00313         return;
00314     Control::activate();
00315     if(!has_frame()){
00316         refresh_viewport();
00317     }
00318 }
00319 
00320 
00321 //-----------------------------------------------------------------------
00322 void Label::deactivate()
00323 {
00324     if(is_hidden())
00325         return;
00326     Control::deactivate();
00327     if(!has_frame()){
00328         refresh_viewport();
00329     }
00330 }
00331 
00332 
00333 /************************************************************************
00334 *   class Button                                                *
00335 ************************************************************************/
00336 //-----------------------------------------------------------------------
00337 Button::Button( Control *parent
00338                                 ,int id,const string &title
00339                                 ,int lines,int cols,int y, int x
00340                                 ,int style)
00341         :Label(parent,id,title,lines,cols,y,x,style)
00342 {
00343 }
00344 
00345 
00346 //-----------------------------------------------------------------------
00347 int Button::driver(int key)
00348 {
00349     int result= FALSE;
00350     switch(key) {
00351         case KEY_ENTER: result = action();  break;
00352 #ifdef NCURSES_MOUSE_VERSION
00353         case KEY_MOUSE:
00354         {
00355             MEVENT  event;
00356             getmouse(&event);
00357             int ry = event.y, rx = event.x; /* screen coordinates */
00358             if (mouse_trafo(&ry,&rx,FALSE)){
00359                 if((event.bstate & (    BUTTON1_CLICKED|
00360                                     BUTTON1_DOUBLE_CLICKED|
00361                                     BUTTON1_TRIPLE_CLICKED))
00362                     && clicked_inside(ry, rx)){
00363                     // we react only if the click was in the userwin, that means
00364                     // inside the menu display area or at the decoration window.
00365                     result=action();
00366                 }
00367             }
00368             break;
00369         }
00370 #endif
00371         default:    result = Label::driver(key); break;
00372     }
00373     return result;
00374 }
00375 
00376 
00377 //-----------------------------------------------------------------------
00378 void Button::activate()
00379 {
00380     Control::activate();
00381     attron(A_BOLD);
00382     set_text(text);
00383     refresh();
00384     
00385 }
00386 
00387 
00388 //-----------------------------------------------------------------------
00389 void Button::deactivate()
00390 {
00391     Control::deactivate();
00392     attroff(A_BOLD);
00393     set_text(text);
00394 }
00395 
00396 
00397 /************************************************************************
00398 *   class PushButton                                                *
00399 ************************************************************************/
00400 //-----------------------------------------------------------------------
00401 PushButton::PushButton( Control *parent
00402                                 ,int id, const string &title
00403                                 ,int lines,int cols,int y, int x
00404                                 ,int style)
00405         :Button(parent,id, title,lines,cols,y,x,(style&=~framed))
00406 {
00407     enable_notify(false);
00408     set_style(framed,true);
00409     set_text(text);
00410     enable_notify();
00411 }
00412 
00413 
00414 //-----------------------------------------------------------------------
00415 PushButton::PushButton( Control *parent
00416                                 ,int id, const string &title
00417                                 ,int y, int x)
00418         :Button(parent,id,title,1,title.size()+3,y,x,tabstop|notify)
00419 {
00420     enable_notify(false);
00421     set_style(framed,true);
00422     set_text(text);
00423     enable_notify(); 
00424 }
00425 
00426 
00427 //-----------------------------------------------------------------------
00428 void PushButton::set_text(const string &v)
00429 {
00430     int max_len = width()-pos_x-has_frame();
00431     string new_text= v.substr(0, max_len); 
00432     text = new_text;
00433     clrtoeol(); 
00434     centertext(0,text.c_str());
00435     if(has_frame()){
00436         addch(0,0, '[');
00437         addch(0,maxx(), ']');
00438     }
00439     move(0,0);
00440     refresh();
00441 }
00442     
00443     
00444 
00445 /************************************************************************
00446 *   class ListItemData                                          *
00447 ************************************************************************/
00448 //----------------------------------------------------------------------//
00449 //      ListItemData::operator=                                 //
00450 //                                                                      //
00451 //      copy from the visible item to the data buffer only gets         //
00452 //      the style and the state of the visible item, since we don't     //
00453 //      allow text or framing changes.                                  //
00454 //                                                                      //
00455 //----------------------------------------------------------------------//
00456 ListItemData &
00457 ListItemData::operator=(const ListItem &rha)
00458 {
00459     set_styles(rha.get_style());
00460     set_states(rha.get_state());
00461     set_default(rha.is_default());
00462     return *this;
00463 }
00464 
00465 
00466 //-----------------------------------------------------------------------
00467 ListItemData &
00468 ListItemData::operator=(const ListItemData &rha)
00469 {
00470     set_text(rha.get_text());
00471     set_ctrl_id(rha.get_ctrl_id());
00472     set_styles(rha.get_style());
00473     set_states(rha.get_state());
00474     set_default(rha.is_default());
00475     set_user_data(rha.get_user_data());
00476     return *this;
00477 }
00478 
00479 
00480 //-----------------------------------------------------------------------
00481 int
00482 ListItemData::set_state(int s,bool on)
00483 { 
00484     int old_state=field_state;
00485     if (on) field_state|=s;
00486     else    field_state&=~s;
00487     return old_state;
00488 }  
00489 
00490 
00491 /************************************************************************
00492 *   class ListItem                                              *
00493 ************************************************************************/
00494 //-----------------------------------------------------------------------
00495 ListItem::ListItem( Control *parent
00496                                 ,int id, const string &title
00497                                 ,int lines,int cols,int y, int x
00498                                 ,int style)
00499         :Button(parent,id, title,lines,cols,y,x,style),user_data(0)
00500 {
00501 }
00502 
00503 
00504 //-----------------------------------------------------------------------
00505 int ListItem::driver(int key)
00506 {
00507     int result= FALSE;
00508     switch(key) {
00509         case ' ':
00510             set_check(!is_checked());
00511             result=TRUE;
00512             break;
00513 #ifdef NCURSES_MOUSE_VERSION
00514         case KEY_MOUSE:
00515         {
00516             MEVENT  event;
00517             getmouse(&event);
00518             if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
00519             && wenclose(w,event.y, event.x))
00520             {   // we react only if the click was in the userwin, that means
00521                 // inside the menu display area or at the decoration window.
00522                 set_check(!is_checked());
00523                 result=TRUE;
00524             }
00525         }
00526 #endif /* NCURSES_MOUSE_VERSION */
00527         default:
00528             break;
00529     }
00530     return result;
00531 }
00532 
00533 
00534 //-----------------------------------------------------------------------
00535 void ListItem::set_text(const string &v)
00536 {
00537     string new_text= v; //.substr(0,width()); 
00538     text = new_text;
00539     refresh_text();
00540     move(0,0);
00541     refresh();
00542 }
00543 
00544 
00545 //-----------------------------------------------------------------------
00546 ListItem &ListItem::operator=(const ListItemData &rha)
00547 {
00548     set_text(rha.get_text());
00549     set_ctrl_id(rha.get_ctrl_id());
00550     set_styles(styles(rha.get_style()));
00551     set_states(states(rha.get_state()));
00552     set_default(rha.is_default());
00553     set_user_data(rha.get_user_data());
00554     return *this;
00555 }
00556 
00557 
00558 /************************************************************************
00559 *   class RadioButton                                               *
00560 ************************************************************************/
00561 //-----------------------------------------------------------------------
00562 RadioButton::RadioButton( Control *parent
00563                                 ,int id,const string &title
00564                                 ,int lines,int cols
00565                                 ,int y, int x,int style)
00566     :ListItem(parent,id,title,lines,cols,y,x,style)
00567 {   
00568     enable_notify(false);
00569     set_text(text);
00570     enable_notify();
00571 }
00572 
00573 
00574 //-----------------------------------------------------------------------
00575 RadioButton::RadioButton( Control *parent
00576                                 ,int id, const string &title
00577                                 ,int y, int x)
00578     :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
00579 {
00580     enable_notify(false);
00581     set_text(text);
00582     enable_notify();
00583 }
00584 
00585 
00586 /************************************************************************
00587 *   class CheckButton                                           *
00588 ************************************************************************/
00589 //-----------------------------------------------------------------------
00590 CheckButton::CheckButton( Control *parent
00591                                 ,int id,const string &title
00592                                 ,int lines,int cols
00593                                 ,int y, int x,int style)
00594         :ListItem(parent,id,title,lines,cols,y,x,style)
00595 {
00596     enable_notify(false);
00597     set_text(text);
00598     enable_notify();
00599 }
00600 
00601 
00602 //-----------------------------------------------------------------------
00603 CheckButton::CheckButton( Control *parent
00604                                 ,int id,const string &title
00605                                 ,int y, int x)
00606     :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
00607 {
00608     enable_notify(false);
00609     set_text(text);
00610     enable_notify();
00611 }
00612 
00613 
00614 /************************************************************************
00615 *   class Edit                                              *
00616 ************************************************************************/
00617 //-----------------------------------------------------------------------
00618 Edit::Edit( Control *parent
00619                                 ,int id,const string &title
00620                                 ,int lines,int cols,int y, int x
00621                                 ,int style)
00622         :Label(parent,id,title,lines,cols,y,x,style)
00623 {
00624 }
00625 
00626 
00627 //-----------------------------------------------------------------------
00628 Edit::~Edit()
00629 {
00630     if(has_frame())
00631         delete viewport;
00632 }
00633 
00634 
00635 //-----------------------------------------------------------------------
00636 int Edit::driver(int key)
00637 {
00638     if(key==KEY_MOUSE)
00639         return false;
00640     return edit(key);
00641 }
00642 
00643 
00644 //-----------------------------------------------------------------------
00645 void Edit::add_char(int key)
00646 {
00647     if(cur_x < text.size())
00648         text[cur_x]=key;
00649     else
00650         text+=key;
00651 }
00652 
00653 
00654 //-----------------------------------------------------------------------
00655 void Edit::insert_char(int key)
00656 {
00657     if(text.size()+1 <= max_len()){
00658         text.insert(cur_x,1,(char)key);
00659     }
00660 }
00661 
00662 
00663 //-----------------------------------------------------------------------
00664 int Edit::add_or_insert_char(int key)
00665 {
00666     if(!isprint(key))
00667         return FALSE;
00668         
00669     if(cur_x > -1 && cur_x < max_len()){
00670         if(overwrite())add_char(key);
00671         else{ 
00672             if(text.size()==max_len()){
00673                 beep();
00674                 return TRUE;
00675             }
00676             insert_char(key);
00677         }
00678         refresh_text();
00679         if(++cur_x >= viewport->width())
00680             x_start++;
00681 //      send_to_log(text) << ":" << cur_x << endl;
00682         refresh_viewport();
00683         if(notify_enabled())
00684             process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00685     }
00686     else beep();
00687     return TRUE;
00688 }
00689 
00690 
00691 //-----------------------------------------------------------------------
00692 int Edit::edit(int key)
00693 {
00694     switch(key) {
00695         case KEY_BACKSPACE:
00696         case KEY_DC:
00697             if(!text.empty()){
00698                 if(cur_x)   cur_x--;
00699                 if(x_start) x_start--;
00700                 text.erase(cur_x,1);
00701                 refresh_text();
00702                 refresh_viewport();
00703                 if(notify_enabled())
00704                     process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00705             }
00706             else beep();
00707             return TRUE;
00708         case KEY_LEFT:  return move_left();
00709         case KEY_RIGHT: return move_right();
00710         case KEY_ENTER: beep(); return KEY_TAB;
00711         default:
00712             if(add_or_insert_char(key)) 
00713                 return TRUE;
00714     }
00715     return FALSE;
00716 }
00717 
00718 
00719 //-----------------------------------------------------------------------
00720 int Edit::move_right()
00721 {
00722     int result=TRUE;
00723     if(text.size() && cur_x < text.size() && cur_x < max_len()-1){
00724         if(++cur_x >= viewport->width()){
00725             x_start++;
00726             refresh_text();
00727         }
00728         refresh_viewport();
00729     }
00730     else 
00731         result = Label::move_right();
00732     return result;
00733 }
00734 
00735 
00736 //-----------------------------------------------------------------------
00737 int Edit::move_left()
00738 {
00739     int result = TRUE;
00740     if(cur_x){
00741         if(--cur_x == x_start){
00742             if(x_start)
00743                 x_start--;
00744             refresh_text();
00745         }
00746         refresh_viewport();
00747     }
00748     else 
00749         result = Label::move_left();
00750     return result;
00751 }
00752 
00753 
00754 /************************************************************************
00755 *   class EditNumber                                                    *
00756 ************************************************************************/
00757 //-----------------------------------------------------------------------
00758 int EditNumber::edit(int key)
00759 {
00760     switch(key) {
00761         case KEY_BACKSPACE:
00762         case KEY_DC:
00763         case KEY_LEFT:
00764         case KEY_RIGHT:
00765         case KEY_ENTER:
00766             return Edit::edit(key);
00767         default:
00768             if(isdigit(key))
00769                 return Edit::edit(key);
00770             else
00771                 beep();
00772             break;
00773     }
00774     return FALSE;
00775 }
00776 
00777 
00778 /************************************************************************
00779 *   class EditDate                                                      *
00780 ************************************************************************/
00781 //-----------------------------------------------------------------------
00782 EditDate::EditDate( Control *parent,int id,const string &msk
00783                     ,int lines,int cols,int y, int x
00784                     ,int style)
00785         :EditNumber(parent,id,msk,lines,cols,y,x,style)
00786         ,mask(msk)
00787 {
00788     enable_notify(false);
00789     set_overwrite();
00790     set_text(mask);
00791     enable_notify();
00792 }
00793 
00794 
00795 //-----------------------------------------------------------------------
00796 EditDate::EditDate( Control *parent
00797                                 ,int id, const string &msk
00798                                 ,int y, int x,int style)
00799         :EditNumber(parent,id,msk
00800                     ,1+((style&framed==framed)*2)
00801                     ,msk.size()+((style&framed==framed)*2)
00802                     ,y,x,style)
00803         ,mask(msk)
00804 {
00805     enable_notify(false);
00806     set_overwrite();
00807     set_text(mask);
00808     enable_notify();
00809 }
00810 
00811 
00812 //-----------------------------------------------------------------------
00813 int EditDate::edit(int key)
00814 {
00815     int result = FALSE;
00816     switch(key) {
00817         case KEY_LEFT:
00818             result = Edit::edit(key);
00819             if(text[cur_x]=='/' || text[cur_x]=='-'){
00820                 result = Edit::edit(key);
00821             }
00822             break;
00823         case KEY_BACKSPACE:
00824         case KEY_DC:
00825             if(cur_x==0)
00826                 beep();
00827             else{
00828                 if(text[cur_x-1]=='/' || text[cur_x-1]=='-'){
00829                     cur_x--;
00830                     refresh_viewport();
00831                 }
00832                 result = Edit::edit(key);
00833                 text.insert(cur_x,1,mask[cur_x]);
00834                 refresh_text();
00835                 refresh_viewport();
00836             }
00837             break;
00838         case '0':
00839         case '1':
00840         case '2':
00841         case '3':
00842         case '4':
00843         case '5':
00844         case '6':
00845         case '7':
00846         case '8': 
00847         case '9': 
00848         case KEY_ENTER:
00849         case KEY_RIGHT:
00850             result = Edit::edit(key);
00851             if(text[cur_x]=='/' || text[cur_x]=='-'){
00852                 result = Edit::edit(KEY_RIGHT);
00853             }
00854             break;
00855         default:
00856             beep();
00857             break;
00858     }
00859     return result;
00860 }
00861 
00862 
00863 /************************************************************************
00864 *   class EditDouble                                                        *
00865 ************************************************************************/
00866 //-----------------------------------------------------------------------
00867 int EditDouble::edit(int key)
00868 {
00869     switch(key) {
00870         case '.':
00871             return Edit::edit(key);
00872         default:
00873             return EditNumber::edit(key);
00874             break;
00875     }
00876     return FALSE;
00877 }
00878 
00879 
00880 /************************************************************************
00881 *   class ListBox                                                   *
00882 ************************************************************************/
00883 //-----------------------------------------------------------------------
00884 
00885 ListBox::ListBox( Control *parent
00886                     ,int id,const string &title
00887                     ,int lines,int cols,int y, int x
00888                     ,int style)
00889         :Control( parent,id,lines,cols,y,x,style)
00890             ,pos_x(0), pos_y(0)
00891             ,curr_item(-1)
00892             ,first_visible(-1)
00893             ,last_visible(-1)
00894             ,cur_sel(-1)
00895 {
00896     enable_notify(false);
00897     if(has_frame()){
00898         pos_x++;
00899         pos_y++;
00900     }
00901     set_text(title);
00902     draw_scrollbar();
00903     enable_notify();
00904 }
00905 
00906 
00907 ListBox::ListBox(int id,const string &title
00908                     ,int lines,int cols,int y, int x
00909                     ,int style)
00910         :Control( id,lines,cols,y,x,style)
00911             ,pos_x(0), pos_y(0)
00912             ,curr_item(-1)
00913             ,first_visible(-1)
00914             ,last_visible(-1)
00915             ,cur_sel(-1)
00916 {
00917     enable_notify(false);
00918     if(has_frame()){
00919         pos_x++;
00920         pos_y++;
00921     }
00922     set_text(title);
00923     draw_scrollbar();
00924     enable_notify();
00925 }
00926 
00927 
00928 //-----------------------------------------------------------------------
00929 BEGIN_BINDINGS(ListBox,Control)
00930     ON_NOTIFY_RANGE(LI_SEL_CHANGE,0,0xffff,ListBox::on_sel_change)
00931 END_BINDINGS()
00932 
00933 
00934 //-----------------------------------------------------------------------
00935 
00936 ListBox::~ListBox()
00937 {
00938     hide();
00939     VisibleItems::iterator it;
00940     for(it=items.begin();it!=items.end();it++){
00941         delete *it;
00942     }
00943     
00944     delete_data();
00945 }
00946 
00947 
00948 //-----------------------------------------------------------------------
00949 void ListBox::delete_data()
00950 {
00951     ListItems::iterator d;
00952     for(d=data.begin();d!=data.end();d++){
00953         delete *d;
00954     }
00955 }
00956 
00957 
00958 //-----------------------------------------------------------------------
00959 void ListBox::clear()
00960 {
00961     delete_data();
00962     data.clear();
00963     curr_item=first_visible=last_visible=0;
00964     refresh_items();
00965     show_empty();
00966     draw_scrollbar();
00967     refresh();
00968 }
00969 
00970 
00971 //-----------------------------------------------------------------------
00972 void ListBox::show_empty()
00973 {
00974     if(data.empty()){
00975         cur_sel=-1;
00976         items[0]->set_text("Empty");
00977         items[0]->enable(false);
00978     }
00979 
00980 }
00981 
00982 
00983 //-----------------------------------------------------------------------
00984 void ListBox::draw_scrollbar()
00985 {
00986     if(!has_vscrollbar())
00987         return;
00988     int i, row, col, h_len, v_len;
00989     int winheight=items.size();
00990     int dataheight = data.size();
00991     int top = ((first_visible==-1)? 0:first_visible);
00992 
00993     if(dataheight==0)
00994         dataheight = 1;
00995         
00996     v_len = (winheight*winheight + dataheight - 1)/dataheight;
00997     if (v_len==0)
00998       v_len = 1;
00999     if (v_len > winheight)
01000       v_len = winheight;
01001 
01002 
01003     row  = (top * winheight + dataheight - 1) / dataheight;
01004     if (row + v_len > winheight)
01005       row = winheight - v_len;
01006 
01007     vline(1,maxx(),winheight);
01008     attron(A_REVERSE);
01009     if (v_len>=2) {
01010       addch(row+1,maxx(),ACS_UARROW);
01011       for(i=2;i<v_len;i++)
01012         addch(row+i,maxx(),' ');
01013       addch(row+v_len,maxx(),ACS_DARROW);
01014     }
01015     else {
01016       for(i=1;i<=v_len;i++)
01017         addch(row+i,maxx(),' ');
01018     }
01019     attroff(A_REVERSE);
01020 }
01021 //-----------------------------------------------------------------------
01022 
01023 int ListBox::add_item(const string &new_item,int pos
01024                                 ,bool is_default= false,bool make_visible)
01025 {
01026     ListItemData *item=new ListItemData(new_item,data.size());
01027     item->set_default(is_default);
01028     add_item(item,pos,make_visible);
01029 }
01030 
01031 
01032 //-----------------------------------------------------------------------
01033 
01034 int ListBox::add_item(ListItemData *new_item,int pos
01035                                                     ,bool make_visible)
01036 {
01037     int old_current = curr_item;
01038     ///by default, we insert at the end
01039     ListItems::iterator where=data.end();
01040     
01041     if(pos!=-1 ){
01042         if(pos >-1 && pos < data.size()){
01043             where=data.begin()+pos;
01044             if(make_visible){
01045                 curr_item=pos;
01046             }
01047         }
01048         else
01049             throw
01050                 Exception<ListBox>(this
01051                                     ,"Position out of range in add_item");
01052     }
01053     else{
01054         if(data.empty()==false){/// if no data, curr_item already is 0
01055             if(make_visible){
01056                 curr_item++;
01057             }
01058         }
01059     }
01060     data.insert(where,new_item);
01061     adjust_visible_items();
01062     draw_scrollbar();
01063     refresh();
01064 }
01065 
01066 
01067 //-----------------------------------------------------------------------
01068 
01069 int ListBox::remove_item(int pos)
01070 {
01071     if(pos>=0 && pos < data.size()){
01072         data.erase(data.begin()+pos);
01073         if(pos<= curr_item && curr_item)
01074             curr_item--;
01075         if(cur_sel == pos){
01076             if(is_multisel()){
01077                 cur_sel = -1;
01078                 adjust_visible_items();
01079                 draw_scrollbar();
01080                 show_empty();
01081                 refresh();
01082             }
01083             else if(cur_sel!=-1)
01084                 set_cur_sel(curr_item);
01085         }
01086     }
01087 };
01088 
01089 
01090 //-----------------------------------------------------------------------
01091 int ListBox::refresh()
01092 {
01093     for( int idx=first_visible;idx <= last_visible; idx++){
01094         if(idx!=curr_item)
01095             deactivate_item(idx);
01096     }
01097     activate_item(curr_item);
01098 }
01099 
01100 
01101 //-----------------------------------------------------------------------
01102 void ListBox::refresh_items()
01103 {
01104     for( int idx=first_visible;idx <= last_visible; idx++){
01105         update_item(idx);
01106     }
01107     clear_items();
01108 
01109 }
01110 
01111 
01112 //-----------------------------------------------------------------------
01113 void ListBox::clear_items()
01114 {
01115     for( int idx=data.size()-first_visible;idx <items.size(); idx++){
01116         items[idx]->set_text("");
01117     }
01118 }
01119 
01120 
01121 //-----------------------------------------------------------------------
01122 
01123 int ListBox::driver (int key)
01124 {
01125     if( data.size()
01126         && curr_item!=-1
01127 //      && (is_multisel() || cur_sel==-1)
01128         && visible_item(curr_item)->driver(key)==TRUE)
01129         return TRUE;
01130     switch(key) {
01131         case KEY_UP:    
01132             return move_up();   
01133         case KEY_DOWN:  
01134             return move_down();
01135         case KEY_RIGHT:
01136             return move_right();
01137         case KEY_LEFT:
01138             return move_left();
01139 #ifdef NCURSES_MOUSE_VERSION
01140         case KEY_MOUSE:
01141         {
01142             MEVENT  event;
01143             getmouse(&event);
01144             if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
01145             && wenclose(w,event.y, event.x))
01146             {   // we react only if the click was in the userwin, that means
01147                 // inside the menu display area or at the decoration window.
01148                 int ry = event.y, rx = event.x; /* screen coordinates */
01149 
01150                 if (mouse_trafo(&ry,&rx,FALSE)){
01151                     set_cur_pos(first_visible + (ry-begy()-1));
01152                     if (event.bstate & BUTTON1_DOUBLE_CLICKED)
01153                         set_cur_sel(curr_item);
01154                     return true;
01155                 }
01156             }
01157             break;
01158         }
01159 #endif /* NCURSES_MOUSE_VERSION */
01160         default:
01161             break;
01162     }
01163     return FALSE;
01164 }
01165 
01166 
01167 //-----------------------------------------------------------------------
01168 void ListBox::adjust_visible_items()
01169 {
01170     
01171     if(curr_item < first_visible){
01172         first_visible = curr_item;
01173         last_visible = first_visible + (items.size()-1);
01174     }
01175     if(curr_item > last_visible){
01176         last_visible = curr_item;
01177         first_visible = last_visible - (items.size()-1);
01178         if(first_visible < 0)
01179             first_visible =0;
01180     }
01181     
01182     if(first_visible > data.size()) first_visible = (data.size()-1);
01183     if(last_visible > data.size() || items.size() >= data.size())
01184         last_visible = (data.size()-1);
01185         
01186     if(first_visible < 0) first_visible =0;
01187     if(last_visible < 0) last_visible =0;
01188     
01189     refresh_items();
01190 }
01191 
01192 
01193 //-----------------------------------------------------------------------
01194 
01195 void ListBox::activate()
01196 {
01197     Control::activate();
01198     attron(A_BOLD);
01199     set_text(_title);
01200     attroff(A_BOLD);
01201     draw_scrollbar();
01202     refresh();
01203 }
01204 
01205 
01206 //-----------------------------------------------------------------------
01207 
01208 void ListBox::deactivate()
01209 {
01210     Control::deactivate();
01211     attron(A_BOLD);
01212     set_text(_title);
01213     attroff(A_BOLD);
01214     deactivate_item(curr_item);
01215     draw_scrollbar();
01216     refresh();
01217 }
01218 
01219 
01220 //-----------------------------------------------------------------------
01221 
01222 void ListBox::show_text(const string &t,char where)
01223 {
01224     if (!t.empty()){
01225         switch(where){
01226             case 'l': lefttext(0,t.c_str()); break;
01227             case 'c': centertext(0,t.c_str()); break;
01228             case 'r': righttext(0,t.c_str()); break;
01229             default: centertext(0,t.c_str()); break;
01230         }
01231     }
01232 }
01233 
01234 
01235 //-----------------------------------------------------------------------
01236 
01237 void ListBox::lefttext(int row,const char *label) {
01238   if (label) {
01239     OnError(addstr(row, 1, label, width()));
01240   }
01241 }
01242 
01243 
01244 //-----------------------------------------------------------------------
01245 
01246 void ListBox::righttext(int row,const char *label) {
01247   if (label) {
01248     int x = maxx() - strlen(label)-1;
01249     if (x<0)
01250       x=0;
01251     OnError(addstr(row, x, label, width()));
01252   }
01253 }
01254 
01255 
01256 //-----------------------------------------------------------------------
01257 
01258 void ListBox::activate_item(int item_idx)
01259 {
01260     update_item(item_idx);
01261     visible_item(item_idx)->activate();
01262 }
01263 
01264 
01265 //-----------------------------------------------------------------------
01266 
01267 void ListBox::deactivate_item(int item_idx)
01268 {
01269     visible_item(item_idx)->deactivate();
01270     update_data(item_idx);
01271 }
01272 
01273 
01274 //-----------------------------------------------------------------------
01275 
01276 void ListBox::update_data(int item_idx)
01277 {
01278     if(data.empty()||item_idx<0||item_idx >= data.size() )
01279         return;
01280     ListItem &itm= *(visible_item(item_idx));
01281     ListItemData &dat = *(data[item_idx]);
01282     dat = itm;
01283     
01284 }
01285 
01286 
01287 //-----------------------------------------------------------------------
01288 
01289 void ListBox::update_item(int item_idx)
01290 {
01291     if(data.empty()||item_idx<0||item_idx >= data.size() )
01292         return;
01293     ListItem &itm= *(visible_item(item_idx));
01294     ListItemData &dat = *(data[item_idx]);
01295     itm = dat;
01296 }
01297 
01298 
01299 //-----------------------------------------------------------------------
01300 
01301 int ListBox::move_up()
01302 {
01303     if(curr_item){
01304         curr_item--;
01305         adjust_visible_items();
01306         draw_scrollbar();
01307         refresh();
01308         if(!is_multisel() && cur_sel!=-1)
01309             visible_item(curr_item)->set_check();
01310         if(notify_enabled()){
01311             process_message(pParent,LI_POS_CHANGE,get_ctrl_id(),0);
01312         }
01313     }
01314     return true;
01315 }
01316 
01317 
01318 //-----------------------------------------------------------------------
01319 
01320 int ListBox::move_down()
01321 {
01322     if(data.size() && curr_item < data.size()-1){
01323         curr_item++;
01324         adjust_visible_items();
01325         draw_scrollbar();
01326         refresh();
01327         if(!is_multisel()&& cur_sel!=-1)
01328             visible_item(curr_item)->set_check();
01329         if(notify_enabled()){
01330             process_message(pParent,LI_POS_CHANGE,get_ctrl_id(),0);
01331         }
01332     }
01333     return true;
01334 }
01335 
01336 
01337 //-----------------------------------------------------------------------
01338 string ListBox::get_item_text(int pos){
01339     string result;
01340     if(pos>-1 && pos < data.size())
01341         result = data[pos]->get_text();
01342 
01343     return result;
01344 }
01345 
01346 
01347 //-----------------------------------------------------------------------
01348 void ListBox::set_item_text(int pos,const string &txt)
01349 {
01350     if(pos>-1 && pos < data.size())
01351         data[pos]->set_text(txt);
01352 }
01353 
01354 
01355 //-----------------------------------------------------------------------
01356 int ListBox::sel_string(int pos,const string &txt)
01357 {
01358     ListItems::iterator it;
01359     for(int i=pos;i<data.size();i++){
01360         if(data[i]->text.find(txt)!=string::npos){
01361             set_cur_sel(i);
01362             return i;
01363         }
01364     }
01365     return string::npos;
01366 }
01367 
01368 
01369 //-----------------------------------------------------------------------
01370 void *ListBox::get_item_data(int pos)
01371 {
01372     void *result=0;
01373     if(pos>-1 && pos < data.size())
01374         result = data[pos]->get_user_data();
01375 
01376     return result;
01377 }
01378 
01379 
01380 //-----------------------------------------------------------------------
01381 void ListBox::set_item_data(int pos,void *usr_data)
01382 {
01383     if(pos>-1 && pos < data.size())
01384         data[pos]->set_user_data(usr_data);
01385 }
01386 
01387 
01388 //-----------------------------------------------------------------------
01389 ListItemData *ListBox::get_item(int pos)
01390 {
01391     ListItemData *result=0;
01392     if(pos>-1 && pos < data.size())
01393         result = data[pos];
01394 
01395     return result;
01396 }
01397 
01398 
01399 //-----------------------------------------------------------------------
01400 void ListBox::set_item(int pos,ListItemData *item)
01401 {
01402     if(pos>-1 && pos < data.size()){
01403         delete data[pos];
01404         data[pos]=item;
01405         refresh_items();
01406         refresh();
01407     }
01408 }
01409 
01410 
01411 //-----------------------------------------------------------------------
01412 int ListBox::get_cur_pos()
01413 {
01414     return curr_item;   
01415 }
01416 
01417 
01418 //-----------------------------------------------------------------------
01419 void ListBox::set_cur_pos(int pos)
01420 {
01421     if(pos>-1 && pos < data.size()){
01422         curr_item = pos;
01423         adjust_visible_items();
01424         draw_scrollbar();
01425         refresh();
01426     }
01427 }
01428 
01429 
01430 //-----------------------------------------------------------------------
01431 void ListBox::set_cur_sel(int pos)
01432 {
01433     if(pos>-1 && pos < data.size()){
01434         curr_item = pos;
01435         adjust_visible_items();
01436         draw_scrollbar();
01437         visible_item(pos)->set_check(true);
01438         check_multisel(pos, true);
01439         refresh();
01440     }
01441 }
01442 
01443 
01444 //-----------------------------------------------------------------------
01445 int ListBox::get_cur_sel()
01446 {
01447     if(is_multisel())
01448         throw Exception<ListBox>(this,"Calling get_selected and is_multisel==true");
01449         
01450     return cur_sel; 
01451 }
01452 
01453 
01454 //-----------------------------------------------------------------------
01455 void ListBox::get_sel_items(IndexList &list)
01456 {
01457     list.clear();
01458     if(is_multisel()){
01459         for(int i=0;i<data.size();i++){
01460             if(data[i]->is_checked())
01461                 list.push_back(i);
01462         }
01463     }
01464     else
01465         list.push_back(cur_sel);
01466     
01467 }
01468 
01469 
01470 //-----------------------------------------------------------------------
01471 void ListBox::set_sel_items(const IndexList &list, bool t_or_f)
01472 {
01473     if(is_multisel()){
01474         for(int i=0;i<list.size();i++){
01475             data[list[i]]->set_check(t_or_f);
01476         }
01477     }
01478     refresh_items();
01479     refresh();
01480 }
01481 
01482 
01483 //-----------------------------------------------------------------------
01484 void ListBox::check_multisel(int pos, bool t_or_f)
01485 {
01486     if(!is_multisel()){
01487         if(t_or_f==true){
01488             cur_sel = pos;
01489             for(int i=0;i<data.size();i++){
01490                 if(i != pos){
01491                     data[i]->set_check(false);
01492                     if(i>=first_visible && i<=last_visible){
01493                         update_item(i);
01494                     }
01495                 }
01496             }
01497         }
01498         else //t_or_f == false
01499             cur_sel=-1;
01500     }
01501 }
01502 
01503 
01504 //-----------------------------------------------------------------------
01505 void ListBox::on_sel_change(int id)
01506 {
01507     update_data(curr_item);
01508     check_multisel(curr_item,data[curr_item]->is_checked());
01509     refresh();
01510     if(notify_enabled())
01511         process_message(pParent,LI_SEL_CHANGE,get_ctrl_id(),0);
01512 }   
01513 
01514 
01515 //-----------------------------------------------------------------------
01516 int ListBox::largest_name_len()const{
01517     unsigned MaximumNameLength = 0;
01518     ListItems::const_iterator it;
01519     for(it = data.begin(); it !=data.end();it++){
01520         string name((*it)->get_text());
01521         
01522         if (name.size() > MaximumNameLength ){
01523             MaximumNameLength  = name.size();
01524         }
01525     }
01526     return MaximumNameLength;
01527 }
01528 
01529 
01530 /************************************************************************
01531 *   class SelectionBox                                          *
01532 ************************************************************************/
01533 //-----------------------------------------------------------------------
01534 void SelectionBox::initialize_items()
01535 {
01536     curr_item=first_visible=last_visible=0;
01537     for(int i=pos_y;i<maxy();i++){
01538         items.push_back(new ListItem(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01539     }
01540     show_empty();
01541 }
01542 
01543 
01544 /************************************************************************
01545 *   class CheckListBox                                          *
01546 ************************************************************************/
01547 //-----------------------------------------------------------------------
01548 void CheckListBox::initialize_items()
01549 {
01550     curr_item=first_visible=last_visible=0;
01551     for(int i=pos_y;i<maxy();i++){
01552         items.push_back(new CheckButton(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01553     }
01554     show_empty();
01555 }
01556 
01557 
01558 /************************************************************************
01559 *   class ChoiceBox                                             *
01560 ************************************************************************/
01561 //-----------------------------------------------------------------------
01562 void ChoiceBox::initialize_items()
01563 {
01564     curr_item=first_visible=last_visible=0;
01565     for(int i=pos_y;i<maxy();i++){
01566         items.push_back(new RadioButton(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01567     }
01568     show_empty();
01569 }
01570 
01571 
01572 /************************************************************************
01573 *   class MenuItem                                                  *
01574 ************************************************************************/
01575 //-----------------------------------------------------------------------
01576 MenuItem::MenuItem( Control *parent
01577                                 ,int id,const string &title
01578                                 ,int lines,int cols
01579                                 ,int y, int x,int style)
01580         :ListItem(parent,id,title,lines,cols,y,x,style)
01581 {
01582     enable_notify(false);
01583     set_text(text);
01584     enable_notify();
01585 }
01586 
01587 
01588 //-----------------------------------------------------------------------
01589 MenuItem::MenuItem( Control *parent
01590                                 ,int id,const string &title
01591                                 ,int y, int x)
01592     :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
01593 {
01594     enable_notify(false);
01595     set_text(text);
01596     enable_notify();
01597 }
01598 
01599 
01600 //-----------------------------------------------------------------------
01601 int MenuItem::driver(int key)
01602 {
01603     int result =false;
01604     switch(key){
01605         case KEY_ENTER:
01606             result = pData->action();
01607             break;
01608 #ifdef NCURSES_MOUSE_VERSION
01609         case KEY_MOUSE:
01610         {
01611             MEVENT  event;
01612             getmouse(&event);
01613             if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
01614             && wenclose(w,event.y, event.x))
01615             {   // we react only if the click was in the userwin, that means
01616                 // inside the menu display area or at the decoration window.
01617                 result = pData->action();
01618             }
01619             break;
01620         }
01621 #endif /* NCURSES_MOUSE_VERSION */
01622         default:
01623             result = false;
01624             break;
01625     }
01626     return result;
01627 }
01628 
01629 
01630 /************************************************************************
01631 *   class MenuBar                                                   *
01632 ************************************************************************/
01633 //-----------------------------------------------------------------------
01634 int MenuBar::execute()
01635 {
01636     show();
01637     refresh();
01638     bool bBreakLoop=false;
01639     do{
01640         bBreakLoop=driver(getch());
01641         
01642     } while( bBreakLoop==false);
01643     hide();
01644     refresh();
01645     return bBreakLoop;
01646 }
01647 
01648 
01649 //-----------------------------------------------------------------------
01650 int MenuBar::driver (int key)
01651 {
01652     int result = false;
01653     switch(key) {
01654         case EXIT_APP:
01655         {
01656             string prompt(get_param("exit app","prompt","Esta seguro que quiere salir de la aplicacion?"));
01657             YesNoBox mb(Application::get_application()->get_title(),prompt);
01658             int req =mb.do_modal();
01659             refresh();
01660             if(req==IDYES){
01661                 result=true;
01662             }
01663             break;
01664         }
01665         case KEY_ESC:
01666             if(is_main_menu) ///in this case, KEY_ESC is like EXIT_APP
01667                 result = driver(EXIT_APP);
01668             else result =true;
01669             break;
01670         case KEY_ENTER:
01671             result = execute_current_item(key);
01672                     switch(result) {
01673                         case EXIT_APP:
01674                         case KEY_ESC:
01675                         case KEY_LEFT:
01676                         case KEY_RIGHT:
01677                             return driver(result);
01678                         default:
01679                             break;
01680                     }
01681             break;
01682 #ifdef NCURSES_MOUSE_VERSION
01683         case KEY_MOUSE:
01684         {
01685             MEVENT  event;
01686             getmouse(&event);
01687             if (event.bstate & (BUTTON1_CLICKED)){
01688                 if( wenclose(w,event.y, event.x))
01689                 {   // we react only if the click was in the userwin, that means
01690                     // inside the menu display area or at the decoration window.
01691                     find_clicked();
01692                     result = execute_current_item(key);
01693                     switch(result) {
01694                         case EXIT_APP:
01695                         case KEY_ESC:
01696                         case KEY_LEFT:
01697                         case KEY_RIGHT:
01698                             return driver(result);
01699                         default:
01700                             break;
01701                     }
01702                 }
01703                 else result = true;
01704             }
01705             break;
01706         }
01707 #endif /* NCURSES_MOUSE_VERSION */
01708         default:
01709             result = ListBox::driver(key);
01710             break;
01711     }
01712     return result;
01713 }
01714 
01715 
01716 //-----------------------------------------------------------------------
01717 int MenuBar::execute_current_item(int key)
01718 {
01719     int result=false;
01720     if(curr_item > -1 && curr_item < data.size()){
01721         MenuItem *pItem = dynamic_cast<MenuItem *>(visible_item(curr_item));
01722         if(pItem){
01723             result = pItem->driver(key);
01724         }
01725         refresh();
01726     }
01727     return result;
01728 }
01729 
01730 
01731 //-----------------------------------------------------------------------
01732 int MenuBar::get_next_item_x()
01733 {
01734     int result = 0;
01735     if(orientation=='v'){
01736         result = pos_x;
01737     }
01738     else{
01739         VisibleItems::iterator it;
01740         for(it=items.begin();it!=items.end();it++){
01741             result += (*it)->width();
01742         }
01743     }
01744     return result;
01745 
01746 }
01747 
01748 
01749 //-----------------------------------------------------------------------
01750 int MenuBar::get_next_item_y()
01751 {
01752     int result = 0;
01753     if(orientation=='h'){
01754         result = pos_y;
01755     }
01756     else{
01757         result = items.size();
01758     }
01759     return result+has_frame();
01760 
01761 }
01762 
01763 
01764 //-----------------------------------------------------------------------
01765 void MenuBar::find_clicked()
01766 {
01767     MEVENT  event;
01768     getmouse(&event);
01769     int ry = event.y, rx = event.x; /* screen coordinates */
01770 
01771     if (mouse_trafo(&ry,&rx,FALSE)){
01772         if(clicked_inside(ry,rx)){
01773             for(int i=0;i<items.size();i++){
01774                 if(items[i]->clicked_inside(ry,rx))
01775                     set_cur_pos(first_visible + i );
01776             }
01777         }
01778     }
01779 }
01780 
01781 
01782 /************************************************************************
01783 *   class PopUpMenu                                                     *
01784 ************************************************************************/
01785 //-----------------------------------------------------------------------
01786 int PopUpMenu::action()
01787 {
01788     int result = false;
01789     S = new SubMenu(-1,sub_menu_label
01790                 ,items.size(),largest_name_len()
01791                 ,pMenuItem->begy(),pMenuItem->begx(),'v');
01792     S->items_owner(false);
01793     ListItems::iterator it;
01794     for(it=items.begin();it!=items.end();it++){
01795         S->add_item((MenuItemData *)*it);
01796     }
01797     S->set_cur_pos(cur_sel);
01798     result = S->execute();
01799     cur_sel = S->get_cur_pos();
01800     refresh();
01801     delete S;
01802 
01803     return false;
01804 }
01805 
01806 
01807 //-----------------------------------------------------------------------
01808 int PopUpMenu::largest_name_len()const{
01809     unsigned MaximumNameLength = 0;
01810     ListItems::const_iterator it;
01811     for(it = items.begin(); it !=items.end();it++){
01812         string name((*it)->get_text());
01813         
01814         if (name.size() > MaximumNameLength ){
01815             MaximumNameLength  = name.size();
01816         }
01817     }
01818     if(sub_menu_label.size() > MaximumNameLength)
01819         MaximumNameLength = sub_menu_label.size();
01820     return MaximumNameLength;
01821 }
01822 
01823 
01824 //-----------------------------------------------------------------------
01825 
01826 PopUpMenu::~PopUpMenu()
01827 {
01828     delete S;
01829 //  ListItems::iterator d;
01830 //  for(d=items.begin();d!=items.end();d++){
01831 //      delete *d;
01832 //  }
01833 }
01834 
01835 
01836 /************************************************************************
01837 *   class DialogBox                                                 *
01838 ************************************************************************/
01839 //-----------------------------------------------------------------------
01840 DialogBox::DialogBox(int id,const string &title
01841                         ,int lines, int cols,int y, int x,int d_style, int c_style)
01842     : Control(id,lines,cols,y,x,c_style)
01843         ,_title(title)
01844         ,curr_child(0),
01845         dlg_style(d_style),
01846         changed(false),
01847         pBtnYes(0),
01848         pBtnNo(0),
01849         pBtnCancel(0),
01850         pBtnOk(0)
01851 {
01852     leaveok(FALSE); 
01853     if(has_frame()){    
01854         frame();
01855     }
01856     if(has_show_title()){
01857         show_text(_title,'c');
01858     }
01859 }
01860 
01861 
01862 //-----------------------------------------------------------------------
01863 DialogBox::DialogBox(Control *parent,int id,const string &title
01864                         ,int lines, int cols,int y, int x,int d_style, int c_style)
01865     : Control(parent,id,lines,cols,y,x,c_style)
01866         ,_title(title)
01867         ,curr_child(0),
01868         dlg_style(d_style),
01869         changed(false),
01870         pBtnYes(0),
01871         pBtnNo(0),
01872         pBtnCancel(0),
01873         pBtnOk(0)
01874 {
01875     leaveok(FALSE); 
01876     if(has_frame()){    
01877         frame();
01878     }
01879     if(has_show_title()){
01880         show_text(_title,'c');
01881     }
01882 }
01883 
01884 
01885 //-----------------------------------------------------------------------
01886 BEGIN_BINDINGS(DialogBox,Control)
01887     ON_COMMAND(IDOK,DialogBox::on_dlg_ok)
01888     ON_COMMAND(IDYES,DialogBox::on_dlg_yes)
01889     ON_COMMAND(IDNO,DialogBox::on_dlg_no)
01890     ON_COMMAND(IDCANCEL,DialogBox::on_dlg_cancel)
01891 END_BINDINGS()
01892 
01893 //-----------------------------------------------------------------------
01894 DialogBox::~DialogBox()
01895 { 
01896     hide();
01897     ListOfChildren::iterator it;
01898     for(it=children.begin();it!=children.end();it++){
01899         (*it)->hide();
01900         delete *it;
01901     }
01902 }
01903 
01904         
01905 //-----------------------------------------------------------------------
01906 int DialogBox::do_modal()
01907 {
01908     on_dlg_init();
01909     bContinueModal=true;
01910     int req=REQ_DLG_EXIT;
01911     do{
01912         req=driver(getch());
01913         switch(req){
01914             case REQ_DLG_EXIT:  
01915                 on_dlg_cancel();
01916                 break;
01917 
01918             case REQ_DLG_LEFT:
01919             case REQ_DLG_PREV:  
01920                 prev_control();
01921                 break;
01922             
01923             case REQ_DLG_RIGHT:
01924             case REQ_DLG_NEXT:  
01925                 next_control(); 
01926                 break;
01927 
01928             default:            on_cmd(req);    break;
01929         }   
01930     } while( bContinueModal);
01931     hide();
01932     return user_request;
01933 }
01934 
01935 
01936 //-----------------------------------------------------------------------
01937 void DialogBox::hide()
01938 {
01939     ListOfChildren::iterator it;
01940     for(it=children.begin();it!=children.end();it++){
01941         (*it)->hide();
01942     }
01943     Control::hide();
01944 }
01945 
01946 
01947 //-----------------------------------------------------------------------
01948 void DialogBox::show()
01949 {
01950     ListOfChildren::iterator it;
01951     for(it=children.begin();it!=children.end();it++){
01952         (*it)->show();
01953     }
01954     Control::show();
01955 }
01956 
01957 
01958 //-----------------------------------------------------------------------
01959 void DialogBox::show_text(const string &t,char where)
01960 {
01961     if (!t.empty()){
01962         switch(where){
01963             case 'l': lefttext(0,t.c_str()); break;
01964             case 'c': centertext(0,t.c_str()); break;
01965             case 'r': righttext(0,t.c_str()); break;
01966             default: centertext(0,t.c_str()); break;
01967         }
01968     }
01969 }
01970 
01971 
01972 //-----------------------------------------------------------------------
01973 int DialogBox::driver (int key)
01974 {
01975 
01976 #ifdef NCURSES_MOUSE_VERSION
01977         if(key == KEY_MOUSE){
01978             find_clicked();
01979         }
01980 #endif /* NCURSES_MOUSE_VERSION */
01981 
01982     int result;
01983     if(!children.empty() && curr_child > -1) {
01984         result=children[curr_child]->driver(key);
01985         switch(result){
01986             case TRUE:      return REQ_DLG_PROCESSED;
01987             case KEY_TAB:   return REQ_DLG_NEXT;
01988             case KEY_SHIFT_TAB: return REQ_DLG_PREV;
01989             case KEY_ESC: key = result;
01990             default: break;
01991         }
01992     }
01993     
01994     switch(key) {
01995         case KEY_UP:    return REQ_DLG_UP;
01996         case KEY_DOWN:  return REQ_DLG_DOWN;
01997         case KEY_LEFT:  return REQ_DLG_LEFT;
01998         case KEY_RIGHT: return REQ_DLG_RIGHT;
01999         case KEY_EXIT:
02000         case CTRL('X'):
02001         case KEY_ESC:
02002                         ///same as if user press Cancel button
02003                         user_request=IDCANCEL; 
02004                         return REQ_DLG_EXIT;
02005         case KEY_TAB +0x2f: return REQ_DLG_PREV;
02006         case KEY_TAB:   return REQ_DLG_NEXT;
02007         default: return(key);
02008     }
02009 }
02010 
02011 
02012 //-----------------------------------------------------------------------
02013 void DialogBox:: add_child(int pos,Control *new_child)
02014 { 
02015     ListOfChildren::iterator where=children.end();
02016     if(pos >-1 && pos < children.size()){
02017         where=children.begin()+pos;
02018     }
02019     
02020     if(where==children.end())
02021         add_child(new_child);
02022     else{
02023         where++;
02024         children.insert(where,new_child);
02025     }
02026 }   
02027 
02028 
02029 //-----------------------------------------------------------------------
02030 void DialogBox::find_clicked()
02031 {
02032     MEVENT  event;
02033     getmouse(&event);
02034     int ry = event.y, rx = event.x; /* screen coordinates */
02035 
02036     if (mouse_trafo(&ry,&rx,FALSE)){
02037         if(clicked_inside(ry,rx)){
02038             for(int i=0;i<children.size();i++){
02039                 if(children[i]->clicked_inside(ry,rx))
02040                     set_focus_to(i);
02041             }
02042         }
02043     }
02044 }
02045 
02046 
02047 //-----------------------------------------------------------------------
02048 void DialogBox:: add_child(Control *after,Control *new_child)
02049 { 
02050     ListOfChildren::iterator where;
02051     for(where=children.begin();after && where!=children.end();where++){
02052         if(*where==after){
02053 //          send_to_log("After found!")<< endl;
02054             break;
02055         }
02056     }
02057     if(where==children.end())
02058         add_child(new_child);
02059     else{
02060         where++;
02061         children.insert(where,new_child);
02062     }
02063 }   
02064 
02065 //-----------------------------------------------------------------------
02066 void DialogBox::next_control()
02067 {
02068     if(children.size()>1 && on_ctrl_term(*(children[curr_child]))){
02069         int start_point=curr_child;
02070         for(curr_child++;start_point!=curr_child;curr_child++){
02071             if(curr_child==children.size())
02072                 curr_child=0;
02073             
02074             if(children[curr_child]->is_enabled())
02075                 break; //We found the next selectable child
02076         }
02077         on_ctrl_init(*(children[curr_child]));
02078     }
02079 }
02080 
02081 
02082 //-----------------------------------------------------------------------
02083 void DialogBox::prev_control()
02084 {
02085     if(children.size()>1 && on_ctrl_term(*(children[curr_child]))){
02086         int start_point=curr_child;
02087         for(curr_child--;start_point!=curr_child;curr_child--){
02088             if(curr_child<0)
02089                 curr_child=children.size()-1;
02090             
02091             if(children[curr_child]->is_enabled())
02092                 break; //We found the next selectable child
02093         }
02094         on_ctrl_init(*(children[curr_child]));
02095     }
02096 }
02097 
02098 
02099 //-----------------------------------------------------------------------
02100 void DialogBox::set_focus_to(int child_idx)
02101 {
02102     if(children.empty()||curr_child < 0)
02103         return;
02104     if(!children[child_idx]->is_enabled())
02105         return;
02106 
02107     if(on_ctrl_term(*(children[curr_child]))){
02108         curr_child = child_idx;
02109         on_ctrl_init(*(children[curr_child]));
02110     }
02111 }
02112 
02113 
02114 //-----------------------------------------------------------------------
02115 void DialogBox::set_focus_to(Control *p_child)
02116 {
02117     for(int i=0;p_child && i<children.size();i++){
02118         if(children[i] == p_child){
02119             set_focus_to(i);
02120             break;
02121         }
02122     }
02123 }
02124 
02125 
02126 //-----------------------------------------------------------------------
02127 bool DialogBox::can_close()
02128 { 
02129     int result = true;
02130     if(changed){
02131         YesNoCancelBox dlg(titDataChgd,msgAskToSave);
02132         int usr_choice = dlg.do_modal();
02133         switch(usr_choice){
02134             case IDCANCEL: result = false;
02135             case IDYES: 
02136             case IDNO:
02137             default:
02138                 break;
02139         }
02140     }
02141     refresh();
02142     return result;
02143 }
02144 
02145 
02146 //-----------------------------------------------------------------------
02147 void DialogBox::lefttext(int row,const char *label) {
02148   if (label) {
02149     OnError(addstr(row, 0, label, width()));
02150   }
02151 }
02152 
02153 
02154 //-----------------------------------------------------------------------
02155 void DialogBox::righttext(int row,const char *label) {
02156   if (label) {
02157     int x = maxx() - strlen(label);
02158     if (x<0)
02159       x=0;
02160     OnError(addstr(row, x, label, width()));
02161   }
02162 }
02163 
02164 
02165 //-----------------------------------------------------------------------
02166 int DialogBox::my_w = 0;        ///useable width
02167 int DialogBox::btn_w= 0;        ///each button width
02168 int DialogBox::btns=0;          ///number of buttons
02169 int DialogBox::used_width=0;    ///total buttons width          
02170 int DialogBox::spc=0;           ///space between buttons
02171 int DialogBox::X_POS(int pos) 
02172 {
02173     return (((my_w-used_width)/btns)+((btn_w+spc)*pos));
02174 }
02175 
02176 
02177 //-----------------------------------------------------------------------
02178 void DialogBox::create_buttons()
02179 {
02180     switch((dlg_style & 0x00ff)){
02181         case okCancel:  add_ok_cancel();        break;
02182         case yesNo:     add_yes_no();           break;
02183         case yesNoCancel:add_yes_no_cancel();   break;
02184         default:        add_ok();               break;
02185     }
02186 }
02187 
02188 //-----------------------------------------------------------------------
02189 void DialogBox::add_ok()
02190 {
02191     pBtnOk=new PushButton(this,IDOK,lblOk, maxy()-1,(maxx()-9)/2);
02192     add_child(pBtnOk);
02193 
02194     if(!children.empty())
02195         set_focus_to(children.size()-1);
02196 }
02197 
02198 //-----------------------------------------------------------------------
02199 void DialogBox::add_ok_cancel()
02200 {
02201     Control *pCtrl=0;
02202     my_w = width()-2;   ///useable width
02203     btn_w= 9;           ///each button width
02204     btns=2;             ///number of buttons
02205     used_width=btn_w*btns;  ///total buttons width          
02206     spc=2;              ///space between buttons
02207     pBtnOk=new PushButton(this,IDOK,lblOk,maxy()-1,X_POS(0));
02208     add_child(pBtnOk);
02209     pBtnOk->enable(false);
02210     pBtnCancel=new PushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(1));
02211     add_child(pBtnCancel);
02212 }
02213 
02214 
02215 //-----------------------------------------------------------------------
02216 void DialogBox::add_yes_no_cancel()
02217 {
02218     my_w = width()-2;   ///useable width
02219     btn_w= 9;           ///each button width
02220     btns=3;             ///number of buttons
02221     used_width=btn_w*btns;  ///total buttons width          
02222     spc=2;              ///space between buttons
02223     pBtnYes=new PushButton(this,IDYES,lblYes,maxy()-1,X_POS(0));
02224     add_child(pBtnYes);
02225     pBtnNo=new PushButton(this,IDNO,lblNo,maxy()-1,X_POS(1));
02226     add_child(pBtnNo);
02227     pBtnCancel=new PushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(2));
02228     add_child(pBtnCancel);
02229 }
02230 
02231 
02232 //-----------------------------------------------------------------------
02233 void DialogBox::add_yes_no()
02234 {
02235     Control *pCtrl=0;
02236     my_w = width()-2;   ///useable width
02237     btn_w= 9;           ///each button width
02238     btns=2;             ///number of buttons
02239     used_width=btn_w*btns;  ///total buttons width          
02240     spc=2;              ///space between buttons
02241     pBtnYes=new PushButton(this,IDYES,lblYes,maxy()-1,X_POS(0));
02242     add_child(pBtnYes);
02243     pBtnNo=new PushButton(this,IDNO,lblNo,maxy()-1,X_POS(1));
02244     add_child(pBtnNo);
02245 }
02246 
02247 
02248 /************************************************************************
02249 *   class PropertyDialog                                                *
02250 ************************************************************************/
02251 //-----------------------------------------------------------------------
02252 PropertyDialog::PropertyDialog(int id,const string &title,int lines, int cols,int y, int x)
02253     : DialogBox(id,title,lines,cols,y,x,0,Control::title),pBtnApply(pBtnNo)
02254 {
02255 }
02256 
02257 
02258 //-----------------------------------------------------------------------
02259 BEGIN_BINDINGS(PropertyDialog,DialogBox)
02260     ON_COMMAND(IDAPPLY,PropertyDialog::on_apply)
02261     ON_COMMAND(RETURN_TO_PAGE,PropertyDialog::on_return_to_page)
02262     ON_COMMAND(CANCEL_TO_CLOSE,PropertyDialog::cancel_to_close)
02263     ON_COMMAND(FOCUS_TO_BUTTONS,PropertyDialog::on_focus_to_buttons)
02264     ON_NOTIFY_RANGE(PAGE_MODIFIED,0,0xffff,PropertyDialog::on_page_modified)
02265     ON_NOTIFY_RANGE(PAGE_SELECTED,0,0xffff,PropertyDialog::on_page_selected)
02266 END_BINDINGS()
02267 
02268 
02269 //-----------------------------------------------------------------------
02270 PropertyDialog::~PropertyDialog()
02271 { 
02272 }
02273 
02274 
02275 //-----------------------------------------------------------------------
02276 void PropertyDialog::on_dlg_init()
02277 {   
02278     create_buttons(); 
02279     set_focus_to(pBtnCancel);
02280 }
02281 
02282 
02283 //-----------------------------------------------------------------------
02284 void PropertyDialog::create_buttons()
02285 {
02286     Label *pFrame = new Label(this,-1,"",3,width(),maxy()-2,0,framed);
02287     pFrame->enable(false);
02288     add_child(pFrame);
02289     my_w = width()-2;   ///useable width
02290     btn_w= 9;           ///each button width
02291     btns=3;             ///number of buttons
02292     used_width=btn_w*btns;  ///total buttons width          
02293     spc=2;              ///space between buttons
02294     pBtnOk=new PropDlgPushButton(this,IDOK,lblOk,maxy()-1,X_POS(0));
02295     pBtnOk->enable(false);
02296     add_child(pBtnOk);
02297     pBtnApply=new PropDlgPushButton(this,IDAPPLY,lblApply,maxy()-1,X_POS(1));
02298     pBtnApply->enable(false);
02299     add_child(pBtnApply);
02300     pBtnCancel=new PropDlgPushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(2));
02301     add_child(pBtnCancel);
02302 }
02303 
02304 
02305 //-----------------------------------------------------------------------
02306 int PropertyDialog::get_next_tab_pos()
02307 {
02308     int result = 0;
02309     ListOfPages::iterator it;
02310     for(it=pages.begin();it!=pages.end();it++){
02311         result += (*it)->width()-1;
02312     }
02313     if(result)
02314         result--;
02315         
02316     return result;
02317 
02318 }
02319 
02320 
02321 //-----------------------------------------------------------------------
02322 void PropertyDialog::set_selected_page(int page)
02323 {
02324     if(valid_page_number(page))
02325         set_focus_to(pages[page]);
02326 }
02327 
02328 
02329 //-----------------------------------------------------------------------
02330 PropertyPage *PropertyDialog::get_page(int page)
02331 {
02332     if(valid_page_number(page))
02333         return pages[page]->get_page();
02334         
02335     throw Exception<PropertyDialog>(this,"Invalid page number!",-1);
02336 }
02337 
02338 
02339 //-----------------------------------------------------------------------
02340 void PropertyDialog::add_page(PropertyPage *new_page)
02341 { 
02342     Tab *pTab =     new Tab(this,new_page->get_ctrl_id(),new_page->get_text(),0,get_next_tab_pos());
02343     pages.push_back(pTab);  
02344     pTab->set_page(new_page);
02345     add_child(pTab);
02346 }
02347 
02348 
02349 //-----------------------------------------------------------------------
02350 void PropertyDialog::reorder_pages()
02351 {
02352     int pos=0;
02353     ListOfPages::iterator it;
02354     for(it = pages.begin();it!=pages.end();it++){
02355         Tab *pTab = *it;
02356         pTab->mvwin(begy(),begx()+pos);
02357         pos += pTab->width()-1;
02358     }
02359 }
02360 
02361 
02362 //-----------------------------------------------------------------------
02363 void PropertyDialog::cancel_to_close()
02364 {
02365     changed = false;
02366     pBtnOk->enable(false);
02367     pBtnApply->enable(false);
02368     pBtnCancel->set_text(" Close ");
02369 }
02370 
02371 
02372 /************************************************************************
02373 *   class Tab                                                   *
02374 ************************************************************************/
02375 //-----------------------------------------------------------------------
02376 Tab::Tab( Control *parent
02377                                 ,int id, const string &title
02378                                 ,int lines,int cols,int y, int x
02379                                 ,int style)
02380         :Button(parent,id, title,lines,cols,y,x,style|=framed)
02381         ,pPage(0)
02382 {
02383     enable_notify(false);
02384     set_text(text);
02385     enable_notify();
02386 }
02387 
02388 
02389 //-----------------------------------------------------------------------
02390 Tab::Tab( Control *parent
02391                                 ,int id, const string &title
02392                                 ,int y, int x)
02393         :Button(parent,id,title,3,title.size()+3,y,x,tabstop|notify|framed)
02394         ,pPage(0)
02395 {
02396     enable_notify(false);
02397     set_text(text);
02398     enable_notify(); 
02399 }
02400 
02401 
02402 //-----------------------------------------------------------------------
02403 Tab::~Tab()
02404 {
02405     delete pPage;
02406 }
02407 
02408 
02409 //-----------------------------------------------------------------------
02410 void Tab::activate()
02411 {
02412     if(is_hidden())
02413         return;
02414 
02415     if(pPage){
02416         pPage->activate();
02417         pPage->refresh();
02418     }
02419     Control::activate();
02420     attron(A_BOLD);
02421     set_text(text);
02422     if(notify_enabled())
02423         process_message(pParent,PAGE_SELECTED,get_ctrl_id(),this);
02424 }
02425 
02426 
02427 //-----------------------------------------------------------------------
02428 void Tab::deactivate()
02429 {
02430     if(is_hidden())
02431         return;
02432     if(pPage){
02433         pPage->deactivate();
02434     }
02435     Control::deactivate();
02436     attroff(A_BOLD);
02437     set_text(text);
02438 }
02439 
02440 
02441 //-----------------------------------------------------------------------
02442 void Tab::set_text(const string &v)
02443 {
02444     int max_len = width()-pos_x-has_frame();
02445     string new_text= v.substr(0, max_len); 
02446     text = new_text;
02447     clrtoeol(); 
02448     centertext(1,text.c_str());
02449     delch(0,maxx());
02450     delch(0,maxx()-1);
02451     addch(1,maxx()-1, '\\');
02452     move(1,1);
02453     refresh();
02454 }
02455 
02456 
02457 //-----------------------------------------------------------------------
02458 int Tab::driver(int key)
02459 {   int val=0;
02460     switch(key) {
02461 #ifdef NCURSES_MOUSE_VERSION
02462         case KEY_MOUSE:
02463         {
02464             MEVENT  event;
02465             getmouse(&event);
02466             int ry = event.y, rx = event.x; /* screen coordinates */
02467             if (!mouse_trafo(&ry,&rx,FALSE))
02468                 return false;
02469             if(!(event.bstate & (   BUTTON1_CLICKED|
02470                                     BUTTON1_DOUBLE_CLICKED|
02471                                     BUTTON1_TRIPLE_CLICKED))
02472                     ||!pPage->clicked_inside(ry, rx)){
02473                 return false;
02474             }
02475         }
02476 #endif  /// if we got here, passthru
02477         case KEY_TAB:
02478         case KEY_DOWN:
02479         case KEY_ENTER:
02480             val = pPage->process_key(key);
02481             if(val == DialogBox::REQ_DLG_DOWN){
02482                 process_message(pParent,0,(int)FOCUS_TO_BUTTONS,0);
02483                 return TRUE;
02484             }
02485             else if(val== DialogBox::REQ_DLG_EXIT) //user pressed ESC key inside the page
02486                 return KEY_ESC;
02487             else if(key==KEY_MOUSE)
02488                 return key;
02489             else
02490                 activate();
02491             break;
02492         default:    
02493             return Button::driver(key);
02494             break;
02495     }
02496     return FALSE;
02497 }
02498 
02499 
02500 /************************************************************************
02501 *   class PropertyPage                                              *
02502 ************************************************************************/
02503 //-----------------------------------------------------------------------
02504 int PropertyPage::process_key(int key)
02505 {
02506     refresh();
02507     bContinueModal=true;
02508     int req=REQ_DLG_EXIT;
02509     do{
02510 #ifdef NCURSES_MOUSE_VERSION
02511         if(key == KEY_MOUSE){
02512             req=driver(key);
02513             key=0;
02514         }
02515         else
02516 #endif /* NCURSES_MOUSE_VERSION */
02517     
02518         req=driver(getch());
02519         switch(req){
02520             case REQ_DLG_EXIT:
02521             case REQ_DLG_UP:
02522             case REQ_DLG_DOWN:
02523                                 bContinueModal=false;break;
02524             case REQ_DLG_RIGHT: 
02525             case REQ_DLG_NEXT:  next_control(); break;
02526 
02527             case REQ_DLG_LEFT: 
02528             case REQ_DLG_PREV:  prev_control(); break;
02529             default:            on_cmd(req);    break;
02530         }   
02531     } while( bContinueModal);
02532     return req;
02533 }
02534 
02535 
02536 //-----------------------------------------------------------------------
02537 void PropertyPage::on_cmd(int key)
02538 {
02539     switch(key) {
02540 #ifdef NCURSES_MOUSE_VERSION
02541         case KEY_MOUSE:
02542         {
02543             MEVENT  event;
02544             getmouse(&event);
02545             int ry = event.y, rx = event.x; /* screen coordinates */
02546             if (mouse_trafo(&ry,&rx,FALSE)){
02547                 if((event.bstate & (    BUTTON1_CLICKED|
02548                                     BUTTON1_DOUBLE_CLICKED|
02549                                     BUTTON1_TRIPLE_CLICKED))
02550                     && !clicked_inside(ry, rx)){
02551                     // we react only if the click was in the userwin, that means
02552                     // inside the menu display area or at the decoration window.
02553                     bContinueModal=false;
02554                 }
02555             }
02556             break;
02557         }
02558 #endif
02559         default:    break;
02560     }
02561 }
02562 
02563 /************************************************************************
02564 *   class MessageBox                                                    *
02565 ************************************************************************/
02566 //-----------------------------------------------------------------------
02567 MessageBox::MessageBox( const string &title,const string &message,int style)
02568     : DialogBox(10000,title,LINES-15,COLS-30,7,15,style),msg(message)
02569 {
02570 }
02571 
02572 
02573 //-----------------------------------------------------------------------
02574 void MessageBox::on_dlg_init()
02575 {   
02576     set_style(styles(title|framed));
02577     DialogBox::on_dlg_init();
02578     show_message();
02579     create_buttons(); 
02580     if(pBtnCancel)
02581         set_focus_to(pBtnCancel);
02582     else if(pBtnNo)
02583         set_focus_to(pBtnNo);
02584 }
02585 
02586 
02587 //-----------------------------------------------------------------------
02588 void MessageBox::show_message()
02589 {
02590     int max_row_size = width()-4;
02591     int rows = msg.size()/max_row_size;
02592     if(msg.size()%max_row_size)
02593         rows++;
02594     
02595     for(int i=0;i<rows && i< maxy()-3;i++){
02596         string what(msg.substr(max_row_size*i,max_row_size));
02597         centertext(i+2,what.c_str());
02598     }
02599 }
02600 
02601 
02602 /************************************************************************
02603 *   class Application                                           *
02604 ************************************************************************/
02605 //-----------------------------------------------------------------------
02606 void Application::activateStatusBar()
02607 {
02608     pStatusBar = new StatusBar(1,COLS,LINES-1,0);
02609     
02610 }
02611 
02612 
02613 //-----------------------------------------------------------------------
02614 bool Application::section_exists(ifstream &param_file,const string &section_name)
02615 {
02616     string tag("[" + section_name + "]");
02617     string line;
02618     char line_read[255]={0};
02619     for(    param_file.getline(line_read,sizeof(line_read));
02620             param_file.good();
02621             param_file.getline(line_read,sizeof(line_read))){
02622         if(line_read[0] == '['){
02623             line = line_read;
02624             if(line.find(tag)!= string::npos){
02625                 return true;
02626             }
02627         }
02628     }
02629     return false;
02630 }
02631 
02632 
02633 //-----------------------------------------------------------------------
02634 long Application::find_key(ifstream &param_file,const string &section_name,
02635                                 const string &key_name,string &value)
02636 {
02637     long line_beg =0;
02638     if(section_exists(param_file,section_name)){
02639         string line;
02640         string found_key;
02641         char line_read[255]={0};
02642         for(    param_file.getline(line_read,sizeof(line_read));
02643                 param_file.good();
02644                 param_file.getline(line_read,sizeof(line_read))){
02645             line = line_read;
02646             line_beg = param_file.tellg();
02647             line_beg -= line.size();
02648             if(line.empty() || line[0]=='#')///Skip empty and comment lines
02649                 continue;
02650             if(line_read[0] == '[')///Reached the next section
02651                 break;
02652             int from= line.find_first_not_of(" \t");
02653             if(from == string::npos)//Non-empty, but all spaces...
02654                 continue;
02655             int to= line.rfind("#");///allow inline comments
02656             if(to!=string::npos){
02657                 line = line.substr(from,to-from);
02658             }
02659             to= line.find_last_not_of(" \t");
02660             line = line.substr(from,to-from+1);
02661             int eq_sign = line.find('=');
02662             found_key= line.substr(0,eq_sign);
02663             if(found_key == key_name){
02664                 if(to!=eq_sign && eq_sign!=string::npos){//no value...
02665                     value= line.substr(eq_sign+1);
02666                 }
02667                 break;
02668             }
02669         }
02670     }
02671     return line_beg;
02672 }
02673 
02674 
02675 //-----------------------------------------------------------------------
02676 string Application::get_param(const string &section_name,
02677                                 const string &key_name,const string &val)
02678 {
02679     long pos=0;
02680     string value=val;
02681     if(!param_file_name.empty()){
02682         ifstream param_file(param_file_name.c_str());
02683         pos = find_key(param_file,section_name,key_name,value);
02684         if(pos && value.empty())
02685             value=val;
02686     }
02687         
02688     return value;   
02689 }
02690 
02691 
02692 //-----------------------------------------------------------------------
02693 long Application::get_param(const string &section_name,
02694                                 const string &key_name,long val)
02695 {
02696     char txt[255]={0};
02697     ostrstream str_val(txt,sizeof(txt));
02698     str_val << val << ends;
02699     string result = get_param(section_name,key_name, str_val.str());
02700     return atol(result.c_str());
02701 ;
02702 }
02703 
02704 } //namespace NDK_XX

Generated on Thu Oct 10 16:02:07 2002 by doxygen1.2.17