v.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 
00028 
00029 #include <cxxtls/file.h>
00030 #include <cxxtls/ftp.h>
00031 #include <cxxtls/cursorwindow.h>
00032 #include <cxxtls/strtool.h>
00033 #include <iostream>
00034 #include <stdlib.h>
00035 #include <portable_io.h>
00036 #include <fstream>
00037 #include <portable_strstream.h>
00038 
00039 using namespace std;
00040 using namespace cxxtls;
00041 
00042 //@File
00043 //
00049 //
00050 
00051 class DisplayList
00052   //
00058 
00059 {
00060 public:
00061 
00062   typedef list<string>     rep_t;
00063   typedef rep_t::iterator  iterator;
00064 
00065 private:
00066 
00067   rep_t  rep_;
00068   size_t size_;
00069 
00070 public:
00071 
00072   DisplayList()
00073   : size_(0)
00074   {
00075   }
00076 
00077   iterator begin() { return rep_.begin(); }
00078   iterator end()   { return rep_.end();   }
00079 
00080   DisplayList &operator += (string const &s)
00081   {
00082     ++size_;
00083 
00084     rep_.push_back(s);
00085 
00086     return *this;
00087   }
00088 
00089   size_t size() const { return size_; }
00090 
00091 
00092 };
00093 
00094 
00095 class ResizeHandler
00096   //
00104   //
00105 : public CursorWindow::resize_handler
00106 {
00107 
00108 public:
00109 
00110   typedef DisplayList::iterator iterator;
00111   typedef CursorWindow::row_col row_col;
00112 
00113 private:
00114 
00115   DisplayList         *  list_;
00116   iterator               top_;
00117   FileName               title_;
00118   int                    page_offset_;
00119   int                    lines_on_page_;  // real lines on this page
00120 
00121 public:
00122 
00123   ResizeHandler(DisplayList *l, FileName title)
00124   : list_(l),
00125     top_(l->begin()),
00126     title_(title),
00127     page_offset_(0)
00128   {
00129   }
00130 
00131   void operator() (CursorWindow* w)
00132   {
00133 
00134      w->set_curpos(1,0);
00135 
00136      w->set_text_attribute(CursorWindow::normal);
00137 
00138      iterator scan = top_;
00139 
00140      int rows = w->size().row_ - 1;
00141 
00142      lines_on_page_ = 0;
00143 
00144      for(int i = 1; i < rows && scan != list_->end(); ++i, ++scan)
00145      {
00146        ++lines_on_page_;
00147 
00148        if(i == page_offset_ + 1)
00149        {
00150          w->set_text_attribute(CursorWindow::reversed);
00151 
00152          w->write(*scan);
00153          w->fill_to_eol();
00154 
00155          w->set_text_attribute(CursorWindow::normal);
00156        }
00157        else
00158        {
00159          w->write(*scan);
00160          w->fill_to_eol();
00161        }
00162      }
00163 
00164      w->fill_to_eos('_');
00165 
00166      w->set_curpos(0,0);
00167 
00168      w->set_text_attribute(CursorWindow::reversed);
00169 
00170      w->write(title_);
00171      w->fill_to_eol();
00172 
00173      char buffer[40];
00174 
00175      sprintf(buffer, "%lu", (unsigned long)(list_->size()) );
00176 
00177      int l = strlen(buffer);
00178 
00179      w->set_curpos(0, w->size().col_ - l);
00180      w->write(buffer);
00181 
00182 
00183      if(page_offset_ >= lines_on_page_)
00184      {
00185        // we have scrolled down past the bottom of the file
00186        // so the page_offset_ variable isn't valid --
00187        // set it to be the last valid line of the file, if
00188        // any and repaint that line as being marked
00189 
00190        if(lines_on_page_ == 0)
00191          page_offset_ = 0;
00192        else
00193        {
00194 
00195          page_offset_ = lines_on_page_-1;
00196         
00197          int i;
00198         
00199          for(i=0, scan = top_; i < lines_on_page_; ++i, ++scan)
00200          {
00201            if(i == page_offset_)
00202              break;
00203          }
00204         
00205          w->set_curpos(1 + page_offset_, 0);
00206          w->set_text_attribute(CursorWindow::reversed);
00207          w->write(*scan);
00208          w->fill_to_eol();
00209         
00210         
00211        }
00212      }
00213 
00214   }
00215 
00216   void pageup(CursorWindow* w)
00217   {
00218 
00219     int pagesize =  w->size().row_;
00220 
00221     pagesize -= 2;  // 1 for the header, and 1 just to keep context
00222 
00223     while(pagesize && top_ != list_->begin())
00224     {
00225       --pagesize;
00226       --top_;
00227     }
00228 
00229     page_offset_ = 0;
00230 
00231     (*this)(w);  // repaint after scrolling up
00232 
00233 
00234   }
00235 
00236   void pagedown(CursorWindow* w)
00237   {
00238 
00239     int pagesize =  w->size().row_;
00240 
00241     pagesize -= 2;  // 1 for the header, and 1 just to keep context
00242 
00243     iterator save = top_;
00244 
00245     while(pagesize && top_ != list_->end())
00246     {
00247       --pagesize;
00248 
00249       save = top_;
00250 
00251       ++top_;
00252     }
00253 
00254     if(top_ == list_->end()) //make sure we never really get to the
00255                              // end unless the list is empty
00256       top_ = save;
00257 
00258     page_offset_ = 0;
00259 
00260     (*this)(w);  // repaint after scrolling up
00261 
00262 
00263   }
00264 
00265   void lineup(CursorWindow*w)
00266   {
00267     if(page_offset_ == 0)
00268     {
00269       if(top_ == list_->begin())
00270         return;
00271 
00272       --top_;
00273 
00274       (*this)(w);
00275     }
00276     else
00277     {
00278       if(lines_on_page_ == 0)
00279         return;
00280 
00281       int offset = 0;
00282 
00283       iterator ip = top_;
00284 
00285       while(offset != page_offset_)
00286       {
00287         ++offset;
00288         ++ip;
00289       }
00290 
00291       // ip now points to the text of the current line
00292       // paint it in the normal color.
00293 
00294       w->set_text_attribute(CursorWindow::normal);
00295       w->set_curpos(1 + page_offset_, 0);
00296       w->write(*ip);
00297       w->fill_to_eol();
00298 
00299 
00300       //
00301       // now draw the previous line as highlightded
00302       //
00303       --ip;
00304       --page_offset_;
00305 
00306       w->set_text_attribute(CursorWindow::reversed);
00307       w->set_curpos(1 + page_offset_, 0);
00308       w->write(*ip);
00309       w->fill_to_eol();
00310 
00311       w->set_curpos(1 + page_offset_, 0);
00312 
00313 
00314     }
00315 
00316   }
00317 
00318   void linedown(CursorWindow*w)
00319   {
00320     if(lines_on_page_ < 2)
00321       return;
00322 
00323     if(page_offset_ >= lines_on_page_ -1)
00324     {
00325       iterator save = top_;
00326 
00327       if(top_ != list_->end())
00328         ++top_;
00329 
00330       if(top_ == list_->end())
00331         top_ = save;
00332 
00333       (*this)(w);
00334 
00335     }
00336     else
00337     {
00338       int offset = 0;
00339 
00340       iterator ip = top_;
00341 
00342       while(offset != page_offset_)
00343       {
00344         ++offset;
00345         ++ip;
00346       }
00347 
00348       // ip now points to the text of the current line
00349       // paint that line in the non-marked colors
00350 
00351       w->set_text_attribute(CursorWindow::normal);
00352       w->set_curpos(1 + page_offset_, 0);
00353 
00354       w->write(*ip);
00355       w->fill_to_eol();
00356 
00357       // now paint the next line in the marked color
00358 
00359       ++page_offset_;
00360       ++ip;
00361 
00362       w->set_text_attribute(CursorWindow::reversed);
00363       w->set_curpos(1 + page_offset_, 0);
00364       w->write(*ip);
00365       w->fill_to_eol();
00366 
00367       // put the cursor at the beginning of the line
00368 
00369       w->set_curpos(1 + page_offset_, 0);
00370 
00371     }
00372 
00373   }
00374 
00375 };
00376 
00377 static char binary_char='#';
00378 
00379 static void readfile(FileName const &f, DisplayList &l)
00380 {
00381     if(!f.exists())
00382     {
00383       cerr << "Error:   expected existing file or directory" << endl;
00384       exit(1);
00385     }
00386 
00387     fstream file;
00388 
00389     file.open(f.c_str(), ios::in);
00390 
00391     if(file.fail())
00392     {
00393       cerr << "error:  couldn't open " << f << endl;
00394       exit(1);
00395     }
00396 
00397     istreambuf_iterator<char> nc(file);
00398     istreambuf_iterator<char> lc;
00399 
00400     string line;
00401 
00402     while(nc != lc)
00403     {
00404       char c = *nc++;
00405 
00406 
00407       if(c == '\n')
00408       {
00409         l += StrTool::expand_tabs(line,0,binary_char);
00410         line.resize(0);
00411       }
00412       else
00413         line += c;
00414         
00415     }
00416 
00417     if(line.size())
00418       l += StrTool::expand_tabs(line,0,binary_char);
00419 
00420 
00421     file.close();
00422 }
00423 
00424 
00425 int main(int argc, char **argv)
00426 {
00427   if(argc < 2)
00428   {
00429     cerr << "Error:   expected pathname" << endl;
00430     exit(1);
00431   }
00432 
00433   FileName f(argv[1]);
00434 
00435 
00436   DisplayList l;
00437 
00438 
00439   if(f[0] == 'f' &&
00440      f[1] == 't' &&
00441      f[2] == 'p' &&
00442      f[3] == ':' &&
00443      f[4] == '/' &&
00444      f[5] == '/'
00445     )
00446   {
00447     // I am expecting to see  ftp://user:pass@host/directory/file
00448 
00449     string rest(f.begin()+6, f.end());
00450 
00451     size_t slash = rest.find_first_of('/',0);
00452 
00453     if(slash >= rest.size())
00454     {
00455       cerr << "badly formatted ftp file name:  " << f << endl;
00456       cerr << endl;
00457       cerr << "expected ftp://user:pass@host/directory/file" << endl;
00458       exit(1);
00459     }
00460 
00461     string path(rest.begin() + slash, rest.end());
00462 
00463     string user_password_host(rest.begin(), rest.begin() + slash);
00464 
00465     size_t colon = user_password_host.find_first_of(':');
00466 
00467     if(colon >= user_password_host.size())
00468     {
00469       cerr << "badly formatted ftp file name:  " << f << endl;
00470       cerr << endl;
00471       cerr << "expected ftp://user:pass@host/directory/file" << endl;
00472       exit(1);
00473     }
00474 
00475     string user(user_password_host.begin(), user_password_host.begin() + colon);
00476 
00477     string password_host(user_password_host.begin() + colon + 1,
00478                          user_password_host.end()
00479                         );
00480                         
00481     size_t at = password_host.find_first_of('@');
00482 
00483     if(at >= password_host.size())
00484     {
00485       cerr << "badly formatted ftp file name:  " << f << endl;
00486       cerr << endl;
00487       cerr << "expected ftp://user:pass@host/directory/file" << endl;
00488       exit(1);
00489     }
00490 
00491     string password(password_host.begin(),
00492                     password_host.begin() + at
00493                    );
00494                 
00495     string host(password_host.begin() + at + 1,
00496                 password_host.end()
00497                );
00498                 
00499 
00500     std::list<FTP::FileInfo> stats;
00501 
00502     std::list<FTP::FileInfo> target_status;
00503 
00504     bool force_directory_status=false;
00505 
00506     if(FTP::stat_matching(host,
00507                       user,
00508                       password,
00509                       path,
00510                       &target_status
00511                      )
00512       )
00513     {
00514        if(path.size() &&
00515           path[path.size()-1] == '/'
00516          )
00517        {
00518          force_directory_status=true;
00519         
00520        }
00521        else
00522        {
00523          cerr << "No such remote file as " << f << endl;
00524          exit(1);
00525        }
00526 
00527     }
00528 
00529     if(force_directory_status ||
00530        target_status.front().status_.mode.is_dir()
00531       )
00532     {
00533       FileName dirSearchPattern(path);  dirSearchPattern.convertToDirectorySearchPattern();
00534 
00535       FTP::stat_matching(host, user, password, dirSearchPattern, &stats);
00536                 
00537       std::list<FTP::FileInfo>::iterator first=stats.begin(),
00538                                          last =stats.end();
00539                                 
00540       while(first != last)
00541       {
00542          FTP::FileInfo &info = *first++;
00543 
00544          FileStatus& status =  info.status_;
00545 
00546          string line;
00547 
00548          line += status.mode;
00549          line += " ";
00550          line += status.time;
00551          line += " ";
00552 
00553          char buffer[40];
00554 
00555          sprintf(buffer, "%12lu", (unsigned long)status.size);
00556 
00557          line += buffer;
00558          line += " ";
00559          line += info.name_;
00560 
00561          l += line;
00562 
00563       }
00564     }
00565     else
00566     {
00567        // not a directory
00568 
00569       FileName tmp = FileName::mktemp();
00570 
00571       if(FTP::get(host, user, password, path, tmp))
00572       {
00573         cerr << "Error couldn't get remote file " << f << endl;
00574         exit(1);
00575       }
00576 
00577       readfile(tmp, l);
00578 
00579       tmp.remove();
00580 
00581     }
00582 
00583 
00584 
00585   }
00586   else
00587   if(f.is_dir())
00588   {
00589      FileName::sorted_names_t lf;
00590 
00591      FileName dirSearchPattern(f);  dirSearchPattern.convertToDirectorySearchPattern();
00592 
00593      f.find_matching(dirSearchPattern, &lf);
00594 
00595 
00596      f.convert_to_absolute_path();
00597 
00598      FileName::sorted_names_t::iterator f = lf.begin();
00599      FileName::sorted_names_t::iterator e = lf.end();
00600 
00601      while(f != e)
00602      {
00603        FileStatus status;
00604 
00605        f->file_stat(&status);
00606 
00607        string line;
00608 
00609        line += status.mode;
00610        line += " ";
00611        line += status.time;
00612        line += " ";
00613 
00614        char buffer[40];
00615 
00616        sprintf(buffer, "%12lu", (unsigned long)status.size);
00617 
00618        line += buffer;
00619        line += " ";
00620        line += *f;
00621 
00622        l += line;
00623 
00624        ++f;
00625 
00626      }
00627 
00628 
00629   }
00630   else
00631   {
00632 
00633     readfile(f, l);
00634 
00635   }
00636 
00637   CursorWindow w;
00638 
00639   w.open();
00640 
00641   ResizeHandler r(&l, f);
00642 
00643   r(&w);
00644 
00645   w.set_resize_handler(&r);
00646 
00647   for(;;)
00648   {
00649     CursorWindow::input_event e = w.read_input();
00650 
00651     if(e.type_ == CursorWindow::input_event::DataKey)
00652     {
00653       switch(e.value_)
00654       {
00655         case 'q':
00656         case 'Q':
00657         case 0x1b:
00658           return 0;
00659       }
00660     }
00661     else
00662     {
00663       switch(e.value_)
00664       {
00665          case CursorWindow::key_prior:
00666            r.pageup(&w);
00667            break;
00668         
00669          case CursorWindow::key_next:
00670            r.pagedown(&w);
00671            break;
00672         
00673          case CursorWindow::key_up:
00674            r.lineup(&w);
00675            break;
00676         
00677          case CursorWindow::key_down:
00678            r.linedown(&w);
00679            break;
00680         
00681         
00682         
00683       }
00684 
00685     }
00686 
00687 
00688   }
00689 
00690 
00691 
00692 
00693 }
Generated on Wed Feb 29 22:50:03 2012 for CXXUtilities by  doxygen 1.6.3