viewer.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // Copyright 2002, Lowell Boggs Jr.
00004 //
00005 // This file or directory, containing source code for a computer program,
00006 // is Copyrighted by Lowell Boggs, Jr.  987 Regency Drive, Lewisville
00007 // TX (USA), 75067.  You may use, copy, modify, and distribute this
00008 // source file without charge or obligation so long as you agree to
00009 // the following:
00010 //
00011 //  1.  You must indemnify Lowell Boggs against any and all financial
00012 //      obligations caused by its use, misuse, function, or malfunction.
00013 //      Further, you acknowledge that there is no warranty of any kind,
00014 //      whatsoever.
00015 //
00016 //  2.  You agree not to attempt to patent any portion of this original
00017 //      work -- though you may attempt to patent your own extensions to
00018 //      it if you so choose.
00019 //
00020 //  3.  You keep this copyright notice with the file and all copies
00021 //      of the file and do not change it anyway except language translation.
00022 //
00023 // You are responsible for enforcing your own compliance with these
00024 // conditions and may not use this source file if you cannot agree to the
00025 // above terms and conditions.
00026 
00027 
00030 
00031 #include <cxxtls/viewermanager.h>
00032 #include <cxxtls/file.h>
00033 #include <cxxtls/cursesinterface.h>
00034 #include <cxxtls/strtool.h>
00035 #include <cxxtls/foreach.h>
00036 
00037 using namespace std;
00038 
00039 namespace cxxtls
00040 {
00041 
00042 bool ListViewer::policies::is_special(size_t)
00043 {
00044    return false; // default value for non-special lines
00045 }
00046 
00047 inline
00048 int
00049 ListViewer::
00050 line_attribute(bool selected, size_t index, bool is_bottom)
00053   {
00054     int i=0;
00055 
00056     if(selected)                   i += 1;
00057     if(com_->is_marked(index))     i += 2;
00058     if(com_->is_special(index))    i += 4;
00059 
00060     switch(i)
00061     {
00062       case 1:   return active_ ? ViewerManager::highlighted_att
00063                                : ViewerManager::inactive_mark_att;
00064                                // selected but not marked
00065                         
00066       case 2:   return ViewerManager::inactive_mark_att; // marked but not selected
00067 
00068       case 3:   return active_ ? ViewerManager::active_mark_att
00069                                : ViewerManager::inactive_mark_att;
00070 
00071       case 4:   return is_bottom ? CursorWindow::bold_ul : CursorWindow::bold;
00072                 // special, not selected, not marked
00073 
00074       case 5:   return active_ ? CursorWindow::rev_ul_bold
00075                                : CursorWindow::bold_ul;
00076                                // selected and special but not marked
00077                         
00078       case 6:   return ViewerManager::inactive_mark_att; // marked and special but not selected
00079 
00080       case 7:   return active_ ? ViewerManager::active_mark_att
00081                                : CursorWindow::bold_ul;
00082 
00083     }
00084 
00085     // case 0.
00086 
00087     return is_bottom ? ViewerManager::bottom_att : ViewerManager::normal_att;
00088   }
00089 
00090 ListViewer::
00091 policies::
00092 ~policies()
00093 {
00094 }
00095 
00096 void
00097 ListViewer::
00098 policies::
00099 handle_resize(CursorWindow::row_col const &)
00100 {
00101   // by default, do nothing
00102 }
00103 
00104 
00105 void
00106 ListViewer::
00107 operator() ( CursorWindow::viewport * vp,int cmd)
00108 {
00109   // WARNING:  do not save vp -- it gets deleted regularly!
00110 
00111   if(cmd == CursorWindow::viewport::repaint_handler::deactivate)
00112   {
00113     active_ = false;
00114   }
00115   else
00116   if(cmd == CursorWindow::viewport::repaint_handler::activate)
00117   {
00118     active_ = true;
00119   }
00120 
00121   size_t  apps = com_->strings_.size();
00122   row_col vpsize  = vp->size();
00123   row_col vporigin= vp->origin();
00124 
00125   com_->handle_resize(vpsize);   // let policies object know what's
00126                                  // going on.
00127 
00128   int left = 0;
00129 
00130   if(vporigin.col_)  ++left;  // if not left most viewer, add a 1 char bias
00131 
00132 
00133   // erase the viewport -- and underline the bottom line
00134 
00135   vp->set_curpos(0,0);
00136   vp->set_text_attribute(ViewerManager::normal_att);
00137   vp->fill_to_eos();
00138 
00139   if(left)
00140   {
00141     vp->set_text_attribute(CursorWindow::bold);
00142 
00143     for(int i = 0; i < vpsize.row_; ++i)
00144     {
00145       vp->set_curpos(i, 0);
00146 
00147       using namespace CursesInterface;
00148 
00149       vp->write(line_chars[VL_MIDDLE]);
00150     }
00151 
00152     vp->set_text_attribute(ViewerManager::normal_att);
00153   }
00154 
00155 
00156   vp->set_curpos(vpsize.row_-1, left);
00157   vp->set_text_attribute(ViewerManager::bottom_att);
00158   vp->fill_to_eol();
00159 
00160   // display the title line highlighted based on active' flag
00161   // for this paint request
00162 
00163   vp->set_curpos(0,left);
00164 
00165   if(active_)
00166     vp->set_text_attribute(ViewerManager::active_title_att);
00167   else
00168     vp->set_text_attribute(ViewerManager::inactive_title_att);
00169 
00170   {
00171     FileName tmp(com_->title_);
00172 
00173     *vp << tmp.shorten(vpsize.col_);
00174   }
00175 
00176   vp->fill_to_eol();
00177 
00178   // Draw the body of the window by representing each application
00179   // on one line of the display.  The application's address and shortname
00180   // and as much of the full name is presented as possible.
00181 
00182   // The display_top_ member indicates which row of the display is to
00183   // appear as the first entry in the vertical list of apps
00184   // and the cur_row_ indicates which row the cursor is sitting on
00185 
00186 
00187   int row = first_row_;  // actual physical row where display occurs
00188 
00189   // adjust cur_row_ to account for the possiblity of a smaller display
00190   // window than the last time we moved the cursor.
00191   {
00192       size_t avail = vpsize.row_ - row;
00193             
00194       if(cur_row_ - display_top_ >= avail)
00195       {
00196           display_top_ += avail/2;
00197       }
00198   }
00199 
00200 
00201   for(size_t  i = display_top_;
00202       row < vpsize.row_ && i < apps;
00203       ++i, ++row
00204      )
00205   {
00206     int att = line_attribute(i == cur_row_, i, row == vpsize.row_-1);
00207 
00208     vp->set_text_attribute(att);
00209 
00210     if(i == cur_row_)
00211     {
00212       // highlight the current row by making it reversed video
00213 
00214       vp->set_curpos(row, left);
00215       vp->fill_to_eol();
00216 
00217       // leave the text attributes as reversed
00218     }
00219 
00220     vp->set_curpos(row, 2+left);
00221 
00222     output_row_text(vp, i);
00223 
00224     if(att != ViewerManager::normal_att)
00225       vp->fill_to_eol();
00226 
00227   }
00228 
00229   vp->set_text_attribute(ViewerManager::normal_att); // set to normal atts
00230 
00231   vp->set_curpos(first_row_ + cur_row_ - display_top_,left);
00232                           // leave cursor on current line of scrolling display
00233 
00234 }
00235 
00236 bool
00237 ListViewer::
00238 handle_event( CursorWindow::input_event const * e,
00239               CursorWindow::viewport          * vp
00240             )
00241 {
00242   //
00243   //  The ListViewer event handler lets you select a application
00244   //  replace the chooser with that application in the same viewport.
00245   //
00246 
00247   if(e->type_ == CursorWindow::input_event::ForceExitKey)
00248     return true;
00249 
00250 
00251    if(e->type_ != CursorWindow::input_event::DataKey &&
00252       e->type_ != CursorWindow::input_event::FunctionKey
00253      )
00254      return false;
00255 
00256    // unhighlight the current line to be ready for a line
00257    // change
00258 
00259    int     row  = first_row_ + (cur_row_ - display_top_); // screen row
00260    row_col size = vp->size();
00261 
00262    row_col vporigin= vp->origin();
00263 
00264    int left = 0;
00265 
00266    if(vporigin.col_)  ++left;  // if not left most viewer, add a 1 char bias
00267 
00268    vp->set_curpos(row,left);
00269    vp->set_text_attribute(line_attribute(false,
00270                                          cur_row_,
00271                                          (int)(cur_row_ - display_top_) == (size.row_ - first_row_ )-1
00272                                          ));
00273 
00274    *vp << "  ";
00275 
00276    output_row_text(vp, cur_row_);
00277 
00278    vp->fill_to_eol();
00279 
00280    vp->set_curpos(row,left);
00281 
00282    int edit_func = vp->window()->func[e->value_];
00283 
00284    switch(edit_func)
00285    {
00286      case CursorWindow::func_top:
00287        row = first_row_;
00288        cur_row_ = 0;
00289        display_top_ = 0;
00290        vp->activate();
00291        break;
00292 
00293      case CursorWindow::func_bottom:
00294        row = first_row_;
00295        cur_row_ = com_->strings_.size()-1;
00296 
00297        if( (int) cur_row_ < 0)
00298          cur_row_ = 0;
00299         
00300        display_top_ = cur_row_;
00301        vp->activate();
00302        break;
00303 
00304      case CursorWindow::func_up:
00305 
00306        if(com_->strings_.size() == 0)
00307          break;
00308 
00309        // move the cursor up one line and handle paging issues
00310 
00311        if(row == first_row_)
00312        {
00313          if(cur_row_ > 0)
00314          {
00315            --cur_row_;
00316            --display_top_;
00317            repaint(vp);
00318         
00319          }
00320        }
00321        else
00322        {
00323          --row;
00324          --cur_row_;
00325        }
00326 
00327        break;
00328      case CursorWindow::func_down:
00329 
00330        // move the cursor down one line and handle paging issues
00331 
00332        if(com_->strings_.size() == 0)
00333          break;
00334 
00335        if(row == size.row_ - 1 && cur_row_ < com_->strings_.size()-1 )
00336        {
00337           ++cur_row_;
00338           ++display_top_;
00339           repaint(vp);
00340        }
00341        else
00342        {
00343          // not at bottom of viewport
00344         
00345          if(cur_row_ < com_->strings_.size()-1)
00346          {
00347            ++row;
00348            ++cur_row_;
00349          }
00350        }
00351        break;
00352      case CursorWindow::func_prior:
00353 
00354        // move the cursor back one page and handle paging issues
00355 
00356        display_top_ -= size.row_ - first_row_;
00357 
00358        if( (int)(display_top_) < 0)
00359          display_top_ = 0;
00360         
00361        cur_row_ = display_top_;
00362 
00363        row = first_row_;
00364 
00365        repaint(vp);
00366 
00367        break;
00368 
00369      case CursorWindow::func_next:
00370 
00371        // move the cursor forward one page and handle paging issues
00372 
00373        display_top_ += size.row_ - first_row_;
00374 
00375        if( (int)(display_top_) >= (int)com_->strings_.size() )
00376          display_top_ = com_->strings_.size()-1;
00377         
00378        if( (int)(display_top_) < 0 )
00379          display_top_ = 0;
00380         
00381        cur_row_ = display_top_;
00382 
00383        row = first_row_;
00384 
00385        repaint(vp);
00386 
00387        break;
00388 
00389      case CursorWindow::func_find:
00390 
00391        find_string(cur_row_, manager_);
00392 
00393        if( (int)(cur_row_ - display_top_) >= size.row_ - first_row_)
00394        {
00395           display_top_ = cur_row_;
00396 
00397           row = first_row_;
00398 
00399           repaint(vp);
00400        }
00401        else
00402           row = first_row_ + cur_row_ - display_top_;
00403 
00404        break;
00405 
00406      case CursorWindow::func_findnxt:
00407 
00408        find_string(cur_row_);
00409 
00410        if( (int)(cur_row_ - display_top_) >= size.row_ - first_row_)
00411        {
00412           display_top_ = cur_row_;
00413 
00414           row = first_row_;
00415 
00416           repaint(vp);
00417        }
00418        else
00419           row = first_row_ + cur_row_ - display_top_;
00420 
00421        repaint(vp);
00422 
00423        break;
00424 
00425 
00426      default:
00427 
00428       // send all other events to the policies::handle_event member
00429 
00430       {
00431         int rv = com_->handle_event(e, cur_row_, manager_);
00432         
00433         switch(rv)
00434         {
00435           case 0:  break;
00436           case 1:
00437             {
00438               if(cur_row_ >= com_->strings_.size())
00439               {
00440                 cur_row_ = com_->strings_.size() -1;
00441                 
00442                 if( (int)(cur_row_) < 0 )
00443                 {
00444                   cur_row_ = 0;
00445                 }
00446 
00447                 if(display_top_ > cur_row_)
00448                   display_top_ = cur_row_;
00449                 
00450               }
00451               vp->activate();
00452         
00453               row = first_row_ + (cur_row_ - display_top_);
00454             }
00455             break;
00456           case 2:
00457             return true;
00458         }
00459         
00460         if(manager_->active_viewer() !=  this)
00461         {
00462           // this viewer has been displaced from its visible positions,
00463           // so don't draw anything on the screen
00464         
00465           return false;  // we haven't died, we're just invisible
00466         }
00467         
00468       }
00469       break;
00470 
00471    }
00472 
00473    // now, highlight the appropriate line
00474 
00475    row_col saved_curpos = manager_->window()->curpos();
00476 
00477    vp->set_curpos(row,left);
00478    vp->set_text_attribute(line_attribute(true,
00479                                          cur_row_,
00480                                          (int)(cur_row_ - display_top_) == (size.row_ - first_row_ )-1
00481                                         ));
00482 
00483    *vp << "  ";
00484 
00485    output_row_text(vp, cur_row_);
00486 
00487    vp->fill_to_eol();
00488 
00489 
00490    vp->set_curpos(row,left);
00491    vp->set_text_attribute(ViewerManager::normal_att);
00492 
00493    if(vp != manager_->active_viewport())
00494    {
00495      manager_->window()->set_curpos(saved_curpos);
00496    }
00497 
00498 
00499 
00500    return false;
00501 }
00502 
00503 static string toLower(string inp)
00504 {
00505     std::string::const_iterator first = inp.begin(),
00506                                 last  = inp.end();
00507 
00508     string rv;
00509     
00510     
00511     while(first != last)
00512     {
00513        char cur = *first++;
00514 
00515        if(isupper(cur))
00516          cur = tolower(cur);
00517 
00518        rv += cur;
00519     }
00520 
00521     return rv;
00522 
00523 }
00524 
00525 
00526 int
00527 ListViewer::
00528 find_string(size_t index, ViewerManager*vm)
00529 {
00530    CursorWindow::Dialog d("Find String");
00531         
00532    d += new CursorWindow::Dialog::String("name",
00533                                          "String to search for",
00534                                          "",
00535                                          15
00536                                         );
00537                                 
00538    if(d.popup(vm->window()))
00539      return 0;
00540         
00541    search_string_ = toLower(d.element_value("name"));
00542         
00543    if(search_string_.size() == 0)
00544       return 0;
00545 
00546    return find_string(index-1); // may cause a wrap around since index is unsigned
00547 
00548 }
00549 
00550 int
00551 ListViewer::
00552 find_string(size_t index)
00553 {
00554   if(index >= com_->strings_.size())
00555     index = 0;
00556   else
00557     ++index;
00558 
00559   while(index < com_->strings_.size())
00560   {
00561     string curLine = toLower( com_->strings_[index] );
00562 
00563     std::string::iterator match = std::search( curLine.begin(),
00564                                                curLine.end(),
00565                                                search_string_.begin(),
00566                                                search_string_.end()
00567                                              );
00568                                         
00569     if(match != curLine.end())
00570     {
00571       cur_row_ = index;
00572       return 1;             // display_top may not be on same page after return!
00573     }
00574 
00575    ++index;
00576                                         
00577   }
00578 
00579   return 0;
00580 
00581 }
00582 
00583 void Viewer::help()
00584 {
00585   // by default, do nothing.
00586 }
00587 
00588 void
00589 ListViewer::
00590 help()
00591 {
00592   // get the viewer's policy help info
00593 
00594   std::auto_ptr< std::list< std::string > > viewer_help(com_->help_text());
00595 
00596   manager_->help_helper(*viewer_help);
00597 
00598 }
00599 
00600 Viewer::paste_buffer_type*
00601 Viewer::paste_buffer()
00602 {
00603   fetchPasteBuffer();   // on systems that allow it (windows), this function
00604                         // overwrites the current paste buffer with the data
00605                         // in the system clipboard.
00606 
00607   return &manager_->paste_buffer_;
00608 }
00609 
00610 bool
00611 Viewer::is_dirty() const
00612 {
00613   return false;
00614 }
00615 
00616 #ifdef _MSC_VER
00617 
00618 #include <windows.h>
00619 #include <wincon.h>
00620 
00621 #endif
00622 
00623 
00624 void
00625 Viewer::commitPasteBuffer() const
00626 {
00627 #ifdef _MSC_VER
00628   
00629   OpenClipboard(0);
00630 
00631   EmptyClipboard();
00632 
00633   string tmp;
00634 
00635   list<string>::iterator first = manager_->paste_buffer_.begin(),
00636                          last  = manager_->paste_buffer_.end();
00637 
00638   while(first != last)
00639   {
00640     string const &cur = *first++;
00641 
00642     tmp += cur;
00643 
00644     if(first != last)
00645       tmp += "\r\n";
00646   }
00647 
00648   char *buffer = (char*)(GlobalAlloc(GMEM_FIXED, 1 + tmp.size()));
00649 
00650   strcpy(buffer, tmp.c_str());
00651 
00652   SetClipboardData(CF_TEXT, buffer);
00653 
00654   CloseClipboard();
00655 
00656 #else
00657 #endif
00658 }
00659 
00660 void
00661 Viewer::fetchPasteBuffer()
00662 {
00663 #ifdef _MSC_VER
00664  
00665   if(IsClipboardFormatAvailable(CF_TEXT)) 
00666   {
00667     OpenClipboard(0);
00668 
00669     char *p = reinterpret_cast<char*>(GetClipboardData(CF_TEXT));
00670 
00671     if(p)
00672     {
00673       manager_->paste_buffer_.clear();
00674 
00675       string curline;
00676 
00677       while(*p)
00678       {
00679         if(*p == '\r')
00680           ++p;
00681         else
00682         if(*p == '\n')
00683         {
00684           manager_->paste_buffer_.push_back(StrTool::expand_tabs(curline.c_str()));
00685           curline.resize(0);
00686           ++p;
00687         }
00688         else
00689         {
00690           curline += *p++;
00691         }
00692       }
00693 
00694       if(!curline.empty())
00695         manager_->paste_buffer_.push_back(StrTool::expand_tabs(curline.c_str()));
00696 
00697     }
00698 
00699     CloseClipboard();
00700   }
00701 #else
00702 #endif
00703 }
00704 
00705 bool Viewer::fetchAllLines(std::list<std::string> &output)
00706 {
00707    return false;  // by default no viewer supports the fetchAllLinesFeature.
00708 }
00709 
00710 bool
00711 ListViewer::
00712 fetchAllLines(std::list<std::string> &output)
00713 {
00714     if(com_.get())
00715        return com_.get()->fetchAllLines(output);
00716     else
00717        return false;
00718 }
00719 
00720 bool
00721 ListViewer::
00722 policies::
00723 fetchAllLines(std::list<std::string> &output)
00724 {
00725    CXXTLS_FOREACH(std::string const &cur, strings_)
00726       output.push_back(cur);
00727 
00728    return true;
00729 }
00730 
00731 
00732 } // namespace cxxtls
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3