ftpviewer.cxx

Go to the documentation of this file.
00001 //
00002 // Copyright 2002, Lowell Boggs Jr.
00003 //
00004 // This file or directory, containing source code for a computer program,
00005 // is Copyrighted by Lowell Boggs, Jr.  987 Regency Drive, Lewisville
00006 // TX (USA), 75067.  You may use, copy, modify, and distribute this
00007 // source file without charge or obligation so long as you agree to
00008 // the following:
00009 //
00010 //  1.  You must indemnify Lowell Boggs against any and all financial
00011 //      obligations caused by its use, misuse, function, or malfunction.
00012 //      Further, you acknowledge that there is no warranty of any kind,
00013 //      whatsoever.
00014 //
00015 //  2.  You agree not to attempt to patent any portion of this original
00016 //      work -- though you may attempt to patent your own extensions to
00017 //      it if you so choose.
00018 //
00019 //  3.  You keep this copyright notice with the file and all copies
00020 //      of the file and do not change it anyway except language translation.
00021 //
00022 // You are responsible for enforcing your own compliance with these
00023 // conditions and may not use this source file if you cannot agree to the
00024 // above terms and conditions.
00025 //
00026 // Warning:  not all files in this directory structure are covered by the
00027 // same copyright.  Some of them are part of the GNU source distribution
00028 // and you must obey the GPL copyright for those files.
00029 
00034 #include <cxxtls/ftpviewer.h>
00035 #include <cxxtls/ftp.h>
00036 #include <cxxtls/viewermanager.h>
00037 #include <vector>
00038 #include <list>
00039 #include <cxxtls/file.h>
00040 #include <portable_io.h>
00041 #include <cxxtls/strtool.h>
00042 #include <cxxtls/cursesinterface.h>
00043 
00044 namespace cxxtls
00045 {
00046 
00047 // labor saving typedefs
00048 
00049 typedef CursorWindow::viewport       viewport;
00050 typedef CursorWindow::input_event    input_event;
00051 typedef std::string                  string;
00052 typedef std::vector<FTP::FileInfo>   dir_rep;  // directory lines representation
00053 typedef CursorWindow::Dialog         dialog;
00054 typedef dialog::String               string_field;
00055 typedef dialog::Password             password_field;
00056 typedef dialog::Ok                   ok_field;
00057 typedef FTP::FileInfo                file_info;
00058 typedef CursorWindow::Message        message;
00059 typedef CursorWindow::Selection      selection;
00060 typedef FileName::sorted_names_t     filename_list;
00061 typedef std::list<file_info>         fileinfo_list;
00062 typedef std::map<string, FTPviewer*> viewer_map;
00063 
00064 
00066 struct FTPviewer::Impl
00067 //
00068 //  The members of the real FTPviewer class are opaque in the
00069 //  public header, the real members appear in this class.
00070 //
00071 //  Note that all ftp viewer objects are kept in a static list.
00072 //  Never iterate over this list and delete the items in it
00073 //  because the destructor for the Impl class automatically
00074 //  removes itself from the list.  The constructor automatically
00075 //  puts the object in the list...
00076 //
00077 {
00078   void paint        (viewport*          vp, int       cmd);
00079   bool handle_event (input_event const *e,  viewport* vp);
00080   void help();
00081   void paint_row    (viewport*vp, int row, size_t line, bool show_highlights=true);
00082 
00083   static viewer_map  active_viewers_;
00084 
00085   ViewerManager* manager_;
00086   FileName       local_directory_;
00087   FileName       remote_directory_;
00088   string         remote_host_;
00089   string         userid_;
00090   string         password_;
00091   dir_rep        lines_;
00092   bool           is_active_;
00093   size_t         page_top_;
00094   size_t         cur_line_;
00095   int            first_row_;    // first row of actual data display (below titles)
00096   int            visible_rows_;
00097   string         search_;
00098   int            left_margin_;  // first usable column (after border)
00099 };
00100 
00102 viewer_map FTPviewer::Impl::active_viewers_;
00103 
00104 
00106 void 
00107 FTPviewer::
00108 operator() (viewport* vp, int cmd)
00109 {
00110   // WARNING:  do not save vp -- it gets deleted regularly!
00111 
00112   impl_->paint(vp, cmd);
00113 }
00114 
00116 bool 
00117 FTPviewer::
00118 handle_event(input_event const * e,viewport* vp)
00119 {
00120   return impl_->handle_event(e,vp);
00121 }
00122 
00124 void 
00125 FTPviewer::
00126 help()
00127 {
00128   impl_->help();
00129 }
00130 
00132 string 
00133 FTPviewer::
00134 app_name("FTP");
00135 
00137 FTPviewer::
00138 FTPviewer(ViewerManager    *   vm,
00139           FileName    const&   local_directory,
00140           string      const&   remote_host,
00141           string      const&   userid,
00142           string      const&   password,
00143           string      const&   remote_directory
00144          )
00145 :  Viewer(vm),
00146    impl_(new Impl)
00147 {
00148   impl_->active_viewers_[remote_directory] = this;
00149 
00150   impl_->local_directory_ = local_directory;
00151   impl_->remote_host_     = remote_host;
00152   impl_->userid_          = userid;
00153   impl_->password_        = password;
00154   impl_->remote_directory_= remote_directory;
00155   impl_->is_active_       = false;
00156   impl_->first_row_       = 1;          // leave a 1 line title area on each page
00157   impl_->page_top_        = 0;
00158   impl_->cur_line_        = 0;
00159   impl_->visible_rows_    = 0;
00160   impl_->manager_         = vm;
00161   impl_->left_margin_     = 0;
00162 
00163 }
00164 
00166 FTPviewer::
00167 ~FTPviewer()
00168  {
00169     viewer_map::iterator victim = 
00170                      impl_->active_viewers_.find(impl_->remote_directory_);
00171 
00172     if(victim != impl_->active_viewers_.end())
00173     {
00174       impl_->active_viewers_.erase(victim);
00175     }
00176 
00177  }
00179 
00180 string 
00181 FTPviewer::
00182 description() const
00183 {
00184   return impl_->remote_host_ + ":" + impl_->remote_directory_;
00185 }
00186 
00188 Viewer* 
00189 FTPviewer::
00190 app(ViewerManager*vm, string &fullname)
00191 {
00192 
00193 
00194   string   host;
00195   string   user;
00196   string   pwd;
00197   FileName localdir(FileName::getcwd());
00198 
00199   if(fullname != "")
00200   {
00201     // user has tried to specify some of the text on the command line
00202 
00203     StrTool::stringlist_t parts;
00204 
00205     StrTool::parse_words(fullname, &parts);
00206 
00207     size_t count = parts.size();
00208 
00209     if(count >= 1) 
00210     {
00211       host = parts.front();
00212       --count;
00213       parts.erase(parts.begin());
00214     }
00215 
00216     if(count >= 1) 
00217     {
00218       user = parts.front();
00219       --count;
00220       parts.erase(parts.begin());
00221     }
00222 
00223     if(count >= 1) 
00224     {
00225       pwd = parts.front();
00226       --count;
00227       parts.erase(parts.begin());
00228     }
00229 
00230     if(count >= 1) 
00231     {
00232       localdir = parts.front();
00233       --count;
00234       parts.erase(parts.begin());
00235     }
00236 
00237     fullname="";
00238 
00239   }
00240 
00241 
00242 
00243   if(pwd == "")
00244   {
00245     // If the user didn't specify it all, prompt for it
00246 
00247     dialog d("FTP connection");
00248     d += new string_field("host", "Host", host, 20);
00249     d += new string_field("user", "User", user, 20);
00250     d += new password_field("password", "Password", pwd, 20);
00251     d += new string_field("localdir", "Local Directory", localdir, 40);
00252     d += new ok_field("ok", "Ok");
00253     
00254     if(d.popup(vm->window()))
00255       return 0;
00256     
00257     host      = d.element_value("host");
00258     user      = d.element_value("user");
00259     pwd       = d.element_value("password");
00260     localdir  = d.element_value("localdir");
00261   }
00262 
00263 
00264   FTPviewer* rv = new FTPviewer(vm, fullname=localdir, host, user, pwd);
00265 
00266   fileinfo_list lofi;
00267         
00268   int count = FTP::stat_matching(host, user, pwd, "", &lofi);
00269 
00270   if(count < 0)
00271   {
00272     message m("Couldn't connect to remote server");
00273     m += "Ftp error was: ";
00274     m += "   " + FTP::error();
00275     m += "";
00276 
00277     m.popup(vm->window());
00278 
00279     delete rv;
00280     return 0;
00281   }
00282 
00283   rv->impl_->lines_.resize(count);
00284 
00285   std::copy(lofi.begin(), lofi.end(), rv->impl_->lines_.begin());
00286         
00287   return rv;
00288                 
00289 }
00291 void 
00292 FTPviewer::Impl::
00293 paint_row    (viewport*vp, int row, size_t line, bool show_highlights)
00294 {
00295   //
00296   // paint an FTP directory row.
00297   //
00298 
00299   //
00300   // Determine the text attribute for drawing the row
00301   //
00302 
00303   if(line != cur_line_ || !show_highlights)
00304   {
00305     if(row == visible_rows_ - 1)
00306       vp->set_text_attribute(ViewerManager::bottom_att);
00307     else
00308       vp->set_text_attribute(ViewerManager::normal_att);
00309   }
00310   else
00311     vp->set_text_attribute(ViewerManager::highlighted_att);
00312 
00313 
00314   //
00315   //  Position the cursor to the beginning of the row data --
00316   //  skipping any left margin to handle any needed borders.
00317   //
00318 
00319   vp->set_curpos(row + first_row_, left_margin_);
00320 
00321   //
00322   //  compute the text of the directory entry and draw it --
00323   //  unless the line requested is outside the range of valid lines
00324   //
00325 
00326   if(line < lines_.size())
00327   {
00328     //
00329     //  When constructing a string of text to output, take into
00330     //  account the width of the line available.  If insufficient
00331     //  space, leave out things in order to give preference to 
00332     //  the most important parts
00333     //
00334 
00335     file_info &info = lines_[line];
00336 
00337     FileStatus& status =  info.status_;
00338 
00339     string line_text;
00340 
00341     int cols = vp->size().col_;
00342 
00343     if(cols > 30)
00344     {
00345       if(cols >= 69)
00346       {
00347         line_text += status.mode;
00348         line_text += " ";
00349       }
00350 
00351       if(cols >= 60)
00352       {
00353 
00354         line_text += status.time;
00355         line_text += " ";
00356       }
00357 
00358       if(cols >= 42 )
00359       {
00360         char buffer[40];
00361         
00362         sprintf(buffer, "%12lu", (unsigned long)status.size);
00363         
00364         line_text += buffer;
00365       }
00366 
00367       line_text += " ";
00368     }
00369 
00370     line_text += info.name_;
00371 
00372     vp->write(line_text);
00373 
00374   }
00375 
00376   vp->fill_to_eol();
00377 }
00379 void 
00380 FTPviewer::Impl::
00381 paint(viewport* vp, int cmd)
00382 {
00383   //
00384   //  Fully repaint the current window and leave the cursor
00385   //  sitting on the 'current' row of the window
00386   //
00387 
00388 
00389   // When painting, first determine if this window is the active
00390   // window or only being refreshed after a screen resize or
00391   // something.  Save this information in the is_active_ flag.
00392 
00393   if(cmd == viewport::repaint_handler::activate)
00394     is_active_ = true;
00395   else
00396   if(cmd == viewport::repaint_handler::deactivate)
00397     is_active_ = false;
00398 
00399   //
00400   //  Next, determine the size an absolute position of the window.
00401   //  The size is used for computing scrolling information.  The
00402   //  absolute position of the window is used to determine the
00403   //  left margin for drawing.  If the absolute position of the
00404   //  the window is left aligned, then no left border is needed --
00405   //  and thus the left margin is 0.  Per the standard of the
00406   //  viewers, if a left border is needed, it will be a column of
00407   //  vertical bars.
00408   //
00409 
00410   row_col size    = vp->size();
00411   row_col origin  = vp->origin();
00412 
00413   if(origin.col_ == 0)
00414     left_margin_ = 0;
00415   else
00416     left_margin_ = 1;  // skip space for column of '|' characters
00417 
00418 
00419   //
00420   //  Now we know the needed info for drawing.  Start with the title
00421   //  and draw down the page vertically -- handling the data rows
00422   //  and the empty region below them.
00423   //
00424   //
00425   //  handle the title area
00426   //
00427 
00428   vp->set_curpos(0,0);
00429 
00430   if(left_margin_)  // handle left border if needed
00431   {
00432     vp->set_text_attribute(ViewerManager::inactive_mark_att);
00433 
00434     using namespace CursesInterface;
00435 
00436     vp->write(line_chars[VL_MIDDLE]);
00437   }
00438 
00439   if(is_active_)
00440    vp->set_text_attribute(ViewerManager::active_title_att);
00441   else
00442    vp->set_text_attribute(ViewerManager::inactive_title_att);
00443 
00444   *vp << "FTP("
00445       << remote_host_
00446       << "): "
00447       << remote_directory_.shorten(size.col_ - 6 - remote_host_.size())
00448       ;
00449 
00450   vp->fill_to_eol();
00451 
00452   //
00453   // handle the data rows
00454   //
00455 
00456   visible_rows_ = size.row_- first_row_;
00457 
00458   int row; // count of rows processed, not screen pos
00459 
00460   for(row=0; row < visible_rows_; ++row)
00461   {
00462     size_t line = row + page_top_;
00463 
00464     if(line >= lines_.size())
00465       break;
00466 
00467     paint_row(vp, row, line);
00468 
00469     if(left_margin_)
00470     {
00471       vp->set_curpos(row + first_row_, 0);
00472       vp->set_text_attribute(ViewerManager::inactive_mark_att);
00473 
00474       using namespace CursesInterface;
00475 
00476       vp->write(line_chars[VL_MIDDLE]);
00477     }
00478 
00479   }
00480 
00481   //
00482   // Handle the empty region below the last title
00483   //
00484 
00485   vp->set_text_attribute(ViewerManager::normal_att);
00486 
00487   while(row < visible_rows_)
00488   {
00489     vp->set_curpos(row + first_row_, 0);
00490    
00491     if(row == visible_rows_ - 1)
00492       vp->set_text_attribute(ViewerManager::bottom_att);
00493 
00494     vp->fill_to_eol();
00495 
00496     if(left_margin_)
00497     {
00498       vp->set_curpos(row + first_row_, 0);
00499       vp->set_text_attribute(ViewerManager::inactive_mark_att);
00500 
00501       using namespace CursesInterface;
00502 
00503       vp->write(line_chars[VL_MIDDLE]);
00504     }
00505 
00506     ++row;
00507   }
00508 
00509   //
00510   //  Leave the cursor in the correct place for input
00511   //
00512 
00513   vp->set_curpos(cur_line_ - page_top_ + first_row_, left_margin_);
00514 
00515 }
00517 bool 
00518 FTPviewer::Impl::
00519 handle_event (input_event const *e,  viewport* vp)
00520 {
00521 
00522   if(e->type_ == input_event::ForceExitKey)
00523     return true;
00524 
00525 
00526   if(e->type_ != input_event::DataKey &&
00527      e->type_ != input_event::FunctionKey
00528     )
00529     return false;
00530 
00531 
00532   if(lines_.size() == 0 &&
00533      e->value_ != 'p'    &&
00534      e->value_ != '^'
00535     )
00536     return true;  // can't issue commands to empty records -- except for
00537                   // quit, put file to empty page
00538                   // list parent directory
00539 
00540   int edit_func = vp->window()->func[e->value_];
00541 
00542   paint_row(vp, cur_line_ - page_top_, cur_line_, false); 
00543 
00544   // handle key with no highlight of current line, then re-highlight it
00545 
00546   switch(edit_func)
00547   {
00548     case CursorWindow::func_data:
00549       switch(e->value_)
00550       {
00551         case 'q':  // 'q' quits
00552         case 'k':  // 'k' quits too
00553           return true;
00554         
00555         case 'd': // delete a file
00556           {
00557              std::string child_path;
00558         
00559              child_path = remote_directory_;
00560         
00561              if(child_path.size())
00562                child_path += "/";
00563         
00564              FileName curfile = child_path + lines_[cur_line_].name_;
00565         
00566              if(lines_[cur_line_].status_.mode.is_dir())
00567              {
00568                vp->beep();
00569                break;
00570              }
00571         
00572              {
00573                dialog d("Delete file (Esc means NO!)");
00574         
00575                d += new ok_field("ok", string("Delete") + lines_[cur_line_].name_);
00576         
00577                if(d.popup(manager_->window()))
00578                {
00579                  break;
00580                }
00581         
00582              }
00583         
00584              int err = FTP::del(remote_host_,
00585                                 userid_,
00586                                 password_,
00587                                 curfile
00588                                );
00589                                 
00590              if(err < 0)
00591              {
00592                 vp->beep();
00593              }
00594              else
00595              {
00596                lines_.erase(lines_.begin() + cur_line_);
00597                vp->activate();
00598              }
00599         
00600           }
00601           break;
00602         
00603         case 'g': // get a file
00604           {
00605 
00606              std::string child_path;
00607         
00608              child_path = remote_directory_;
00609         
00610              if(child_path.size())
00611                child_path += "/";
00612 
00613              FileName curfile = child_path + lines_[cur_line_].name_;
00614         
00615              if(lines_[cur_line_].status_.mode.is_dir())
00616              {
00617                vp->beep();
00618                break;
00619              }
00620         
00621              {
00622                dialog d("Download " + lines_[cur_line_].name_ + " (esc for no)");
00623         
00624                d += new ok_field("ok", "ok");
00625         
00626                if(d.popup(manager_->window()))
00627                {
00628                  break;
00629                }
00630              }
00631         
00632         
00633              if(FTP::get(remote_host_,
00634                          userid_,
00635                          password_,
00636                          curfile,
00637                          local_directory_ + "/" + lines_[cur_line_].name_
00638                         )
00639                )
00640              {
00641                 message m("Error downloading " + curfile);
00642                 m.popup(manager_->window());
00643              }
00644              else
00645              {
00646                 manager_->window()->beep();
00647                 message m("Download successfull!");
00648                 m.popup(manager_->window());
00649         
00650              }
00651         
00652           }
00653           break;
00654         
00655         case 'p':
00656           {
00657              filename_list filenames;
00658         
00659              int count = FileName::find_matching(local_directory_ + "/*", 
00660                                                  &filenames);
00661         
00662              if(count)
00663              {
00664                selection s("Select a file to upload:");
00665         
00666                filename_list::iterator first = filenames.begin(),
00667                                              last  = filenames.end();
00668         
00669                while(first != last)
00670                {
00671                  string const& cur = *first++;
00672                 
00673                  s += cur;
00674                }
00675         
00676         
00677                if(!s.popup(manager_->window()))
00678                {
00679                   int rc = FTP::put(remote_host_,
00680                                     userid_,
00681                                     password_,
00682                                     remote_directory_ +  "/" +s.selection_
00683                                    );
00684                                 
00685                   if(rc < 0)
00686                   {
00687                     message m("Error putting file");
00688                 
00689                     m += " " + FTP::error();
00690                 
00691                     m.popup( manager_->window() );
00692                   }
00693                   else
00694                   {
00695                     fileinfo_list tmp;
00696                 
00697                     int count = FTP::stat_matching(remote_host_,
00698                                                    userid_,
00699                                                    password_,
00700                                                    remote_directory_ + "/*",
00701                                                    &tmp
00702                                                   );
00703                                                 
00704                     if(count < 0)
00705                     {
00706                       message m("Error:  couldn't re-read remote directory");
00707                       m += "";
00708                       m += "  " + FTP::error();
00709                 
00710                       m.popup(manager_->window());
00711                     }
00712                     else
00713                     {
00714                       lines_.resize(count);
00715                 
00716                       std::copy(tmp.begin(), tmp.end(), lines_.begin());
00717                       vp->activate();
00718                 
00719                     }
00720                 
00721                   }
00722                }
00723         
00724              }
00725              else
00726              {
00727                message m("No files in local directory");
00728                m += "";
00729                m += "  sorry...";
00730         
00731                m.popup(manager_->window());
00732              }
00733         
00734         
00735           }
00736           break;
00737         
00738         case '^':  // go up to the parent directory
00739           {
00740             if(remote_directory_.size() == 0)
00741             {
00742               vp->beep();
00743               break;
00744             }
00745         
00746             FileName curfile = remote_directory_.dirname();
00747         
00748             if(curfile[curfile.size()-1] == '/')
00749             {
00750               curfile.erase(curfile.size()-1);
00751             }
00752         
00753             Viewer*parent_ftp_session = active_viewers_[curfile];
00754         
00755             if(parent_ftp_session) // already have a session for this, show it
00756             {
00757               manager_->activate(parent_ftp_session);
00758               return false;
00759             }
00760         
00761             {
00762               // navigate down into the directory on the remote host
00763         
00764               FTPviewer* newbie = new FTPviewer(manager_,
00765                                                 local_directory_,
00766                                                 remote_host_,
00767                                                 userid_,
00768                                                 password_,
00769                                                 curfile);
00770         
00771               if(newbie)
00772               {
00773                 fileinfo_list lofi;
00774         
00775                 int count = FTP::stat_matching(remote_host_,
00776                                                userid_,
00777                                                password_,
00778                                                curfile + "/*",
00779                                                &lofi
00780                                               );
00781         
00782         
00783                                         
00784                 if(count < 0)
00785                 {
00786                    message m("FTP operation failed");
00787         
00788                    m += "  " + FTP::error();
00789         
00790                    m.popup(manager_->window());
00791                    delete newbie;
00792                 }
00793                 else
00794                 {
00795                   newbie->impl_->lines_.resize(count);
00796         
00797                   std::copy(lofi.begin(), lofi.end(), newbie->impl_->lines_.begin());
00798         
00799                   manager_->add(newbie, local_directory_);
00800         
00801                   return false;  // prevent painting of current window info
00802                                  // that appears below
00803                 }
00804               }
00805             }
00806           }
00807           break;
00808         
00809         
00810         default:
00811           vp->beep();
00812           break;
00813       }
00814       break;
00815 
00816     case CursorWindow::func_find:
00817       {
00818          dialog d("Find file or directory");
00819 
00820          d += new string_field("string", "Search for", "", 20);
00821          d += new ok_field("ok", "ok");
00822         
00823          if(d.popup(manager_->window()))
00824          {
00825            break;
00826          }
00827         
00828          search_ = d.element_value("string");
00829 
00830          size_t scan = cur_line_+1;
00831         
00832          while(scan < lines_.size())
00833          {
00834         
00835            string::iterator start = std::search(lines_[scan].name_.begin(),
00836                                                 lines_[scan].name_.end(),
00837                                                 search_.begin(),
00838                                                 search_.end()
00839                                                );
00840            if(start != lines_[scan].name_.end())
00841            {
00842              // found it
00843         
00844              break;
00845            }
00846         
00847            ++scan;
00848          }
00849         
00850          if(scan == lines_.size())
00851          {
00852            vp->beep();
00853          }
00854          else
00855          {
00856             page_top_ = scan;
00857             cur_line_ = scan;
00858             vp->activate();
00859          }
00860       }
00861       break;
00862 
00863     case CursorWindow::func_findnxt:
00864       {
00865          size_t scan = cur_line_+1;
00866         
00867          while(scan < lines_.size())
00868          {
00869         
00870            string::iterator start = std::search(lines_[scan].name_.begin(),
00871                                                 lines_[scan].name_.end(),
00872                                                 search_.begin(),
00873                                                 search_.end()
00874                                                );
00875            if(start != lines_[scan].name_.end())
00876            {
00877              // found it
00878         
00879              break;
00880            }
00881         
00882            ++scan;
00883          }
00884         
00885          if(scan == lines_.size())
00886          {
00887            vp->beep();
00888          }
00889          else
00890          {
00891             page_top_ = scan;
00892             cur_line_ = scan;
00893             vp->activate();
00894          }
00895       }
00896       break;
00897 
00898     case CursorWindow::func_clreol:
00899       return true;  // ^K quits
00900 
00901     case CursorWindow::func_enter:
00902       {
00903         std::string child_path;
00904         
00905         child_path = remote_directory_;
00906         
00907         if(child_path.size())
00908           child_path += "/";
00909 
00910         FileName curfile = child_path + lines_[cur_line_].name_;
00911         
00912         if(lines_[cur_line_].status_.mode.is_dir())
00913         {
00914           // navigate down into the directory on the remote host
00915         
00916           Viewer* child_ftp_session = active_viewers_[curfile];
00917         
00918           if(child_ftp_session) // already started this viewer, just show it
00919           {
00920             manager_->activate(child_ftp_session);
00921             return false;
00922           }
00923         
00924         
00925           FTPviewer* newbie = new FTPviewer(manager_,
00926                                             local_directory_,
00927                                             remote_host_,
00928                                             userid_,
00929                                             password_,
00930                                             curfile);
00931         
00932           if(newbie)
00933           {
00934             fileinfo_list lofi;
00935         
00936             int count = FTP::stat_matching(remote_host_,
00937                                            userid_,
00938                                            password_,
00939                                            curfile + "/*",
00940                                            &lofi
00941                                           );
00942         
00943         
00944                                         
00945             if(count < 0)
00946             {
00947                message m("FTP operation failed");
00948         
00949                m += "  " + FTP::error();
00950         
00951                m.popup(manager_->window());
00952                delete newbie;
00953             }
00954             else
00955             {
00956               newbie->impl_->lines_.resize(count);
00957         
00958               std::copy(lofi.begin(), lofi.end(), newbie->impl_->lines_.begin());
00959         
00960               manager_->add(newbie, local_directory_);
00961         
00962               return false;  // prevent painting of current window info
00963                              // that appears below
00964             }
00965           }
00966         }
00967         else
00968         {
00969            // download it to a temp file and bring up a viewer on it
00970         
00971            int count = FTP::get(remote_host_,
00972                                 userid_,
00973                                 password_,
00974                                 curfile,
00975                                 "ftp.tmp"
00976                                );
00977                         
00978            if(count < 0)
00979            {
00980              message m("Error downloading file for viewing");
00981         
00982                m += string("Remote file name = ") + lines_[cur_line_].name_;
00983                m += "";
00984                m += "Local file name = ftp.tmp";
00985                m += "";
00986                m += string("Error = ") + FTP::error();
00987         
00988                m.popup( manager_->window() );
00989         
00990            }
00991            else
00992            {
00993              Viewer *v = manager_->open("ftp.tmp");
00994         
00995              if(v)
00996              {
00997                manager_->add(v, string("ftp://") + remote_host_ + "/" + curfile);
00998                return false;
00999              }
01000            }
01001         
01002                         
01003         
01004         }
01005         
01006       }
01007       break;
01008 
01009     case CursorWindow::func_top:
01010       page_top_ = 0;
01011       cur_line_ = 0;
01012       vp->activate();
01013       break;
01014 
01015     case CursorWindow::func_bottom:
01016       if(lines_.size())
01017       {
01018         page_top_ = lines_.size()-1;
01019         cur_line_ = lines_.size()-1;
01020       }
01021       else
01022       {
01023         page_top_ = 0;
01024         cur_line_ = 0;
01025       }
01026       vp->activate();
01027       break;
01028 
01029     case CursorWindow::func_down:
01030 
01031       if(cur_line_ < lines_.size() -1)
01032       {
01033         ++cur_line_;
01034       }
01035 
01036       if(cur_line_ - page_top_ >= size_t(visible_rows_))
01037       {
01038         ++page_top_;
01039 
01040         vp->activate();
01041       }
01042       break;
01043 
01044     case CursorWindow::func_up:
01045 
01046       if(cur_line_)
01047       {
01048         --cur_line_;
01049         
01050         if(cur_line_ < page_top_ )
01051         {
01052           --page_top_;
01053         
01054           vp->activate();
01055         }
01056       }
01057       break;
01058 
01059     case CursorWindow::func_next:
01060 
01061       cur_line_ += visible_rows_;
01062       page_top_ += visible_rows_;
01063 
01064       if(cur_line_ >= lines_.size())
01065       {
01066         cur_line_ = lines_.size() - 1;
01067         page_top_ = cur_line_;
01068       }
01069 
01070       vp->activate();
01071 
01072       break;
01073 
01074     case CursorWindow::func_prior:
01075 
01076       if(page_top_ < size_t(visible_rows_))
01077       {
01078         page_top_ = 0;
01079         cur_line_ = 0;
01080       }
01081       else
01082       {
01083         page_top_ -= visible_rows_;
01084         cur_line_ -= visible_rows_;
01085       }
01086 
01087       vp->activate();
01088       break;
01089   }
01090 
01091   paint_row(vp, cur_line_ - page_top_, cur_line_);
01092 
01093   vp->set_curpos(first_row_ + (cur_line_ - page_top_), 0);
01094 
01095   return false;
01096 
01097 }
01099 void
01100 FTPviewer::Impl::
01101 help()
01102 {
01103   typedef std::list<string> help_text;
01104 
01105   std::auto_ptr< help_text > viewer_help( new help_text );
01106 
01107   viewer_help->push_back("Help for the FTP viewer");
01108 
01109   viewer_help->push_back("  In addition to the standard key bindings");
01110   viewer_help->push_back("  shown later, the text editor interprets");
01111   viewer_help->push_back("  the following parochial key bindings:");
01112   viewer_help->push_back("    ^X ^K -- quits the edit session");
01113   viewer_help->push_back("    ^X  k -- quits the edit session");
01114   viewer_help->push_back("");
01115   viewer_help->push_back("    'g'   -- downloads the file under the cursor");
01116   viewer_help->push_back("    'p'   -- uploads a file from the local directory");
01117   viewer_help->push_back("    'd'   -- deletes the file under the cursor");
01118   viewer_help->push_back("    Enter -- navigates down into sub-directories");
01119   viewer_help->push_back("    '^'   -- navigate up to the parent directory");
01120   viewer_help->push_back("    ^S    -- search for file or directory name fragments");
01121   viewer_help->push_back("    ^N    -- repeat previous search");
01122   viewer_help->push_back("");
01123 
01124 
01125   manager_->help_helper(*viewer_help);
01126 }
01127 
01128 } // namespace cxxtls
01129 
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3