directoryviewer.cxx

Go to the documentation of this file.
00001 #include <cxxtls/directoryviewer.h>
00002 #include <cxxtls/scripttableviewer.h>
00003 #include <cxxtls/user.h>
00004 #include <cxxtls/etagsdb.h>
00005 #include <cxxtls/cpptagdb.h>
00006 #include <cxxtls/foreach.h>
00007 #include <cxxtls/strtool.h>
00008 
00009 #include <errno.h>
00010 #include <string>
00011 #include <algorithm>
00012 #include <iomanip>
00013 
00014 namespace cxxtls
00015 {
00016 
00019 
00020 std::string DirectoryViewer::app_name("DIRECTORY");
00021 
00022 #ifdef _MSC_VER
00023 #define SLASH '\\'
00024 #else
00025 #define SLASH '/'
00026 #endif
00027 
00028 
00029 bool DirectoryViewer::
00030 is_special(size_t index)
00031 {
00032    if(index >= names_.size())
00033      return  false;
00034 
00035    FileMode const &mode = status_[index].mode;
00036 
00037    return     mode.is_dir()
00038           ||  mode.is_link();
00039 }
00040 
00041 
00042 int
00043 DirectoryViewer::
00044 handle_event(CursorWindow::input_event const *e,
00045                    size_t index,
00046                    ViewerManager* vm)
00047   {
00048     if(e->type_ != input_event::FunctionKey &&
00049        e->type_ != input_event::DataKey
00050       )
00051     return 2;  // force a termination
00052 
00053     int edit_func = (*vm->window()).func[e->value_];
00054 
00055     switch(edit_func)
00056     {
00057       default:
00058         if(e->value_ == ('K' - '@'))
00059         {
00060           return 2;
00061         }
00062         
00063         break;
00064 
00065       case CursorWindow::func_enter:
00066         {
00067           view_dir(index, vm);
00068         }
00069         break;
00070         
00071       case CursorWindow::func_mark:
00072         goto mark_one_file;
00073         
00074         
00075       case CursorWindow::func_data:
00076 
00077         if(names_.size() <= index)
00078         {
00079           // sitting on an invalid position
00080         
00081           if( tolower(e->value_) != 'q' )
00082             break;
00083         }
00084         
00085         
00086         switch(e->value_)
00087         {
00088 
00089           case '\\': display_symbolic_link_file_target(index, vm);
00090                      break; 
00091 
00092           case 'q':  return 2;
00093           case 'Q':  return 2;
00094           case 'u':  user_names_ = !user_names_;
00095                      generate_row_text();
00096                      return 1;  // stuff has changed
00097                 
00098           case 'i':  show_ids_ = !show_ids_;
00099                      generate_row_text();
00100                      return 1;  // stuff has changed
00101                 
00102           case 'c':  return copy_file(index, vm);
00103           case '!':  return etags_first(vm);
00104           case '.':  return cpptags_first(vm);
00105           case '?':  return etags_all(vm);
00106           case '/':  return cpptags_all(vm);
00107           case '0':  return cpptagviewer(vm);
00108           case 'r':  return rename_file(index, vm);
00109           case 'R':  return rename_files(vm);
00110           case 'd':  return delete_file(index, vm);
00111           case 'D':  return delete_files(vm);
00112           case 'C':  return copy_files(vm);
00113           case 's':  // drop through
00114           case 'e':  {
00115                        FileName child(fullname_.dirname() + names_[index]);
00116                 
00117                        child.convert_to_absolute_path();
00118                 
00119                        if(child.is_dir())
00120                        {
00121                          FileName dirSearchPattern(child);  dirSearchPattern.convertToDirectorySearchPattern();
00122 
00123                          view_file_or_dir(dirSearchPattern, vm,true);
00124                        }
00125                        else
00126                        {
00127                           Viewer* oldie = vm->find_viewer(child);
00128 
00129                           if(oldie)
00130                           {
00131                             vm->activate(oldie);
00132                           }
00133                           else
00134                           {
00135                             Viewer* newbie = 0;
00136 
00137                             if(e->value_ == 's')
00138                               newbie = vm->open(child);
00139                             else
00140                               newbie = vm->edit(child);
00141                         
00142                             if(newbie)
00143                                vm->add(newbie, child);
00144                           }
00145                        }
00146                         
00147                      }
00148                      break;
00149           case '^':
00150                      {
00151                FileName parent(fullname_.dirname());   // remove the trailing '*'
00152 
00153                // now remove the trailing /
00154 
00155                if(   (parent.size() > 1)
00156                   && (   parent[parent.size()-1] == '/'
00157                       || parent[parent.size()-1] == '\\'
00158                      )
00159                  )
00160                {
00161                  if(parent.size() != 3 || parent[1] != ':')
00162                    parent.erase(parent.size()-1, 1);
00163                }
00164 
00165                
00166                parent = parent.dirname();  // remove the current directory name
00167 
00168                parent.convertToDirectorySearchPattern();
00169                 
00170                        parent.convert_to_absolute_path();
00171                 
00172                        view_file_or_dir(parent, vm,true);
00173                      }
00174                      break;
00175           case 'a':  return change_mode(index, vm);
00176 
00177           case 'm':
00178           mark_one_file:
00179                      {
00180                        // mark current file
00181                 
00182                        marked_files_set::iterator scan = marks_.find(names_[index]);
00183                 
00184                        if(scan == marks_.end())
00185                          marks_.insert(names_[index]);
00186                        else
00187                          marks_.erase(scan);
00188                         
00189                        return 0;
00190                      }
00191                      break;
00192                 
00193           case 'M': return mark_files_by_pattern(vm);
00194         
00195           case 'L':
00196           case 'l':
00197           case 't':
00198                     {
00199                       sortCode_ = onName;
00200 
00201                       if(e->value_ == 'L')
00202                         sortCode_   = onSize;
00203                       else
00204                       if(e->value_ == 't')
00205                          sortCode_  = onTime;
00206 
00207                       read_directory();
00208                       generate_row_text();
00209                     }
00210                     return 1;
00211 
00212            case 'V':
00213              {
00214                 static UserInfo user = UserInfo::get();
00215 
00216                 FileName stvDir = user.home_dir_ + "/.tools_home/stv";
00217 
00218                 if(!stvDir.is_dir())
00219                 {
00220                     CursorWindow::Message s("Error:");
00221 
00222                     static std::string prefix("    ");
00223 
00224                     
00225                       s += "STV script directory not found";
00226                       s += prefix + stvDir;
00227 
00228                     s.popup(vm->window());
00229 
00230                 }
00231                 else
00232                 {
00233                     FileName tmp(stvDir + "/*.sh");
00234 
00235                     FileName::sorted_names_t scripts;
00236 
00237                     tmp.find_matching(tmp.c_str(), &scripts);
00238 
00239                     if(scripts.empty())
00240                     {
00241                         CursorWindow::Message s("Error:");
00242                         
00243                         static std::string prefix("    ");
00244                         
00245                         
00246                           s += "STV script directory has no scripts";
00247                           s += prefix + stvDir;
00248                         
00249                         s.popup(vm->window());
00250                     }
00251                     else
00252                     {
00253                         CursorWindow::Selection s("Select a script:");
00254                         
00255                         FileName::sorted_names_t::const_iterator i;
00256 
00257                         for(i = scripts.begin(); i != scripts.end(); ++i)
00258                            s += *i;
00259                         
00260                         if(!s.popup(vm->window()))
00261                         {
00262                             std::string scriptname(stvDir + "/" + s.selection_);
00263 
00264                             char saved_dir[2048];
00265 
00266                             int err;
00267 
00268                             if( 0 == getcwd(saved_dir, sizeof(saved_dir)) )
00269                             {
00270                                saved_dir[0] = 0;
00271                             }
00272 
00273                             err = chdir( fullname_.dirname().c_str() );
00274 
00275                             Viewer *v;
00276                     
00277                             vm->add(  v = ScriptTableViewer::app(vm, scriptname), s.selection_ );
00278 
00279                             err = chdir(saved_dir);
00280 
00281                             (static_cast<ScriptTableViewer*>(v))->setDir(fullname_);
00282 
00283                             (void)(err);
00284 
00285 
00286                         }
00287 
00288                     }
00289                 }
00290              }
00291              break;
00292                 
00293                 
00294         }
00295 
00296     }
00297 
00298     return 0;
00299 
00300   }
00301 
00302 
00303 bool
00304 DirectoryViewer::
00305 is_marked(size_t index)
00306   {
00307     marked_files_set::iterator scan = marks_.find(names_[index]);
00308 
00309     if(scan == marks_.end())
00310       return false;
00311 
00312     return true;
00313 
00314   }
00315 
00316 void
00317 DirectoryViewer::
00318 display_symbolic_link_file_target(size_t index, ViewerManager*vm)
00319 {
00320 
00321 
00322     FileName f = fullname_.dirname() + names_[index];
00323 
00324     FileStatus st;
00325 
00326     bool error = false;
00327 
00328     if(f.file_stat(&st, true))
00329     {
00330 
00331        error = true;
00332 
00333     }
00334 
00335     error = error | !st.mode.is_link();
00336 
00337     if(error)
00338     {
00339 
00340         CursorWindow::Message d("Error -- file is not a symbolic link");
00341         
00342         d += "                                                        ";
00343         d += std::string(f);
00344         d += "";
00345         d += "";
00346         
00347         d.popup(vm->window());
00348 
00349 
00350        return;
00351     }
00352 
00353 
00354     static std::string indent("    ");
00355 
00356 
00357     CursorWindow::Message d("Link File Information");
00358 
00359     int mode = 0;
00360 
00361     d += "Link Target                                                      ";
00362     d += indent + f.readlink(&mode);
00363     d += "";
00364 
00365 
00366     FileMode fm(mode);
00367 
00368     d += "";
00369     d += "Link permissions (link itself not target):";
00370 
00371     d += indent + std::string(fm);
00372 
00373     d += "";
00374     d += "";
00375 
00376     d.popup(vm->window());
00377 }
00378 
00379 void
00380 DirectoryViewer::
00381 remove_item(size_t index)
00382     // remove the DirectoryViewer data structures associated with the
00383     // file name at the specified index.
00384   {
00385     marked_files_set::iterator scan = marks_.find(names_[index]);
00386 
00387     if(scan != marks_.end())
00388       marks_.erase(scan);
00389 
00390     strings_.erase( strings_.begin() + index );
00391     names_.erase( names_.begin() + index );
00392     status_.erase( status_.begin() + index);
00393 
00394     StreamableString ss;
00395 
00396     ss << "DIRED " << fullname_ << " [" << names_.size() << " files]";
00397 
00398     title_ = ss;
00399 
00400   }
00401 
00402 DirectoryViewer::
00403 DirectoryViewer(std::string const &fullname, bool show_user_names, bool show_ids)
00404   : marked_line_(0xffffffff),
00405     vp_width_(1000),
00406     user_names_(show_user_names),
00407     show_ids_(show_ids),
00408     sortCode_(onName)
00409   {
00410      fullname_ = fullname;
00411 
00412      fullname_.convert_to_absolute_path();
00413 
00414      title_ = std::string("DIRED ") + fullname;
00415 
00416      read_directory();
00417 
00418   }
00419 
00420 struct FileNameComparator
00421 {
00422     bool operator() (FileName const &left, FileName const &right) const
00423     {
00424        int cmp = StrTool::compareInsensitive(left, right);
00425 
00426        if(cmp < 0)
00427           return true;
00428 
00429        return false;
00430     }
00431 };
00432 
00433 static FileNameComparator nameComparator;
00434 
00435 void
00436 DirectoryViewer::
00437 read_directory()
00438   {
00439      marks_.erase(marks_.begin(), marks_.end());
00440      strings_.erase(strings_.begin(), strings_.end());
00441      status_.erase(status_.begin(), status_.end());
00442      names_.erase(names_.begin(), names_.end());
00443 
00444      // find the files matching the specified directory
00445      // search pattern specified in 'fullname'
00446 
00447      file_name_list  l;
00448      int             count = FileName::find_matching(fullname_, &l);
00449 
00450      // create vectors of strings for faster access.  The names_
00451      // vector is raw text of the name, but the strings_ vector
00452      // contains the status info as well.
00453 
00454      names_.resize(count);
00455 
00456      std::copy(l.begin(), l.end(), names_.begin());
00457 
00458      // read the file status of all the files and store in a map
00459      // keyed to the basename of the file (actually, the keyed to the
00460      // strings found in the names_ array
00461 
00462      typedef std::map<FileName, FileStatus> StatMap;
00463 
00464      StatMap statMap;
00465 
00466      FileName dir = fullname_.dirname();
00467 
00468      {
00469        file_name_vector::iterator f, l;
00470        
00471        for(f = names_.begin(), l = names_.end(); f != l; ++f)
00472        {
00473          FileStatus fstat;
00474        
00475          FileName fullpath = dir + std::string("/") + *f;
00476        
00477          fullpath.file_stat(&fstat, true);
00478 
00479          statMap.insert(StatMap::value_type(*f, fstat)); 
00480        
00481        }
00482      }
00483 
00484 
00485      // sort the names of the files in the directory based on the sortCode_
00486      // parameter
00487 
00488 
00489      switch(sortCode_)
00490      {
00491        case onSize:
00492          // sort by the size of the files in descending order
00493          {
00494            typedef std::multimap<unsigned long long, FileName> Table;
00495 
00496            Table map;
00497 
00498 
00499            // read the size of each file and sort the names of the files
00500            // by the size thereof
00501 
00502            file_name_vector::iterator f, l;
00503 
00504            for(f = names_.begin(), l = names_.end(); f != l; ++f)
00505            {
00506              FileStatus fstat;
00507 
00508              StatMap::const_iterator search = statMap.find(*f);
00509 
00510              if(search != statMap.end())
00511              {
00512                fstat = search->second;
00513              }
00514              else
00515                fstat.size = 0;
00516 
00517              Table::value_type entry(fstat.size, *f);
00518              map.insert(entry);
00519 
00520            }
00521 
00522            //
00523            // copy the names back into the names_ vector but in an order
00524            // sorted by the size of the file
00525            //
00526 
00527            Table::const_iterator a, b;
00528 
00529            for(f=names_.begin(), a=map.begin(), b = map.end(); a != b; ++a, ++f)
00530            {
00531              *f = a->second;
00532            }
00533 
00534          }
00535          break;
00536 
00537        case onTime:
00538          // sort by the size of the files in descending order
00539          {
00540            typedef std::multimap<FileTime, FileName> Table;
00541 
00542            Table map;
00543 
00544 
00545            // read the size of each file and sort the names of the files
00546            // by the size thereof
00547 
00548            file_name_vector::iterator f, l;
00549 
00550            for(f = names_.begin(), l = names_.end(); f != l; ++f)
00551            {
00552              FileStatus fstat;
00553 
00554              StatMap::const_iterator search = statMap.find(*f);
00555 
00556              if(search != statMap.end())
00557              {
00558                fstat = search->second;
00559              }
00560              else
00561                fstat.time = FileTime(0); // null ptr to tm struct yields all 0's
00562 
00563              {
00564                  Table::value_type entry(fstat.time, *f);
00565                  map.insert(entry);
00566              }
00567 
00568            }
00569 
00570            //
00571            // copy the names back into the names_ vector but in an order
00572            // sorted by the size of the file
00573            //
00574 
00575            Table::const_iterator a, b;
00576 
00577            for(f=names_.begin(), a=map.begin(), b = map.end(); a != b; ++a, ++f)
00578            {
00579              *f = a->second;
00580            }
00581 
00582          }
00583          break;
00584 
00585        default:
00586          // by default, sort on the name of the files
00587          std::sort(names_.begin(), names_.end(), nameComparator);
00588          break;
00589      }
00590 
00591 
00592      {
00593        // move directories to the top of the list
00594 
00595        file_name_vector directories;
00596        file_name_vector normals;
00597 
00598        file_name_vector::iterator f, l;
00599 
00600        f=names_.begin();
00601        l = names_.end();
00602 
00603        while(f != l)
00604        {
00605          StatMap::const_iterator search = statMap.find(*f);
00606 
00607          if(search != statMap.end())
00608          {
00609            if(search->second.mode.is_dir())
00610            {
00611              directories.push_back(*f);
00612            }
00613            else
00614            {
00615              normals.push_back(*f);
00616            }
00617          }
00618          else
00619            normals.push_back(*f);
00620 
00621 
00622          ++f;
00623        }
00624 
00625        names_.erase(names_.begin(), names_.end());
00626 
00627        for(f=directories.begin(), l = directories.end(); f != l; ++f)
00628          names_.push_back(*f);
00629 
00630        for(f=normals.begin(), l = normals.end(); f != l; ++f)
00631          names_.push_back(*f);
00632 
00633      }
00634 
00635      // now, format the status info
00636 
00637      strings_.resize(count);
00638      status_.resize(count);
00639 
00640      file_name_vector::iterator first = names_.begin(),
00641                                 last  = names_.end();
00642 
00643      file_status_vector::iterator out = status_.begin();
00644 
00645 
00646      string_vector::iterator sout = strings_.begin();
00647 
00648      while(first != last)
00649      {
00650         *sout++ = *first;
00651 
00652         FileStatus stat;
00653 
00654         StatMap::const_iterator search = statMap.find(*first++);
00655 
00656         if(search != statMap.end())
00657           stat = search->second;
00658 
00659         *out++ = stat;
00660         
00661      }
00662 
00663      // strings_ has only an abbreviate representation of the
00664      // useful data at this point
00665   }
00666 
00667 void
00668 DirectoryViewer::
00669 generate_row_text()
00670   {
00672 
00673     StreamableString ss;
00674 
00675     ss << "DIRED " << fullname_ << " [" << names_.size() << " files]";
00676 
00677     title_ = ss;
00678 
00679 
00680     for(size_t row = 0, last=names_.size(); row != last; ++row)
00681       generate_row_text(row);
00682 
00683   }
00684 
00685 void
00686 DirectoryViewer::
00687 generate_row_text(size_t index)
00688     //
00690     //
00691   {
00692 
00693     StreamableString ss;
00694 
00695     if(vp_width_ > 27)
00696     {
00697        ss << std::string(status_[index].mode) << " ";
00698     }
00699 
00700     if(vp_width_ > 51 )
00701     {
00702       ss << std::setw(12)
00703          << status_[index].size
00704          << " "
00705          ;
00706     }
00707 
00708     if(vp_width_ > 64 && show_ids_)
00709     {
00710       if(user_names_)
00711         ss << std::setw(12)
00712            << FileStatus::id2string(status_[index].owner_id)
00713            << " ";
00714       else
00715         ss << std::setw(12)
00716            << status_[index].owner_id
00717            << " ";
00718     }
00719 
00720     if(vp_width_ > 77 && show_ids_)
00721     {
00722       if(user_names_)
00723         ss << std::setw(12)
00724            << FileStatus::group2string(status_[index].group_id)
00725            << " ";
00726       else
00727         ss << std::setw(12)
00728            << status_[index].group_id
00729            << " ";
00730     }
00731 
00732 
00733     if(vp_width_ > 44 )
00734     {
00735       ss << status_[index].time.short_string() << " ";
00736     }
00737 
00738     ss << names_[index];
00739 
00740 
00741     strings_[index] =  ss;
00742   }
00743 
00744 
00745 void
00746 DirectoryViewer::
00747 handle_resize(CursorWindow::row_col const &vp_size)
00748   {
00749     if(vp_width_ != vp_size.col_)
00750     {
00751       // the size has changed
00752 
00753       vp_width_ = vp_size.col_;
00754 
00755       generate_row_text();
00756 
00757     }
00758   }
00759 
00760 int
00761 DirectoryViewer::
00762 copy_file(size_t index, ViewerManager* vm, FileName target_filename )
00763   {
00764     // allow the user to copy the file under the cursor.  Return 0 or 1
00765     // based on whether the target of the copy lies in the current directory.
00766 
00767     target_filename = target_filename.expand_tildes();
00768 
00769     if(index < names_.size())
00770     {
00771       FileName dirname  = fullname_.dirname();
00772       FileName filename = dirname + names_[index];
00773 
00774       if(filename.is_dir())
00775       {
00776         CursorWindow::Message m("Error");
00777         
00778         m += "Sorry, can not copy directories";
00779         m += "                                        ";
00780         m += "Press enter to continue";
00781 
00782         m.popup(vm->window());
00783         return 0;
00784         
00785       }
00786       else
00787       {
00788         FileName target;
00789         
00790         if(std::string(target_filename) == "")
00791         {
00792           CursorWindow::FileSelector  d("Copy file", fullname_ + "*", "");
00793 
00794           target = d.popup(vm->window(), 0);
00795         
00796           if(target.size() == 0)
00797             return 0;
00798 
00799           target = target.expand_tildes();
00800         
00801           if(!target.is_absolute_path())
00802           {
00803               target = dirname + target;
00804           }
00805         }
00806         else
00807           target = target_filename;
00808 
00809         
00810         if(target.is_dir())
00811         {
00812           target += '/';
00813           target += names_[index];
00814         }
00815         
00816         if(target.exists())
00817         {
00818         
00819           CursorWindow::Dialog e("Replace file? (Press Esc to cancel)");
00820         
00821           e += new CursorWindow::Dialog::Ok("name",
00822                                             std::string("Replace file ") + target
00823                                            );
00824           if(e.popup(vm->window()))
00825             return 0;
00826         }
00827         
00828         if(filename.copy(target))
00829         {
00830           // error occurred while copying
00831         
00832           CursorWindow::Message m("Error");
00833           m += "Error copying file: " + names_[index];
00834           m += "                to: " + target;
00835           m += "";
00836           m += "press enter to continue";
00837           m.popup(vm->window());
00838           return 0;
00839         
00840         }
00841         
00842         if(target.dirname() == dirname)
00843         {
00844           read_directory();
00845           generate_row_text();
00846         
00847           return 1;
00848         }
00849         
00850       }
00851     }
00852     return 0;
00853 
00854   }
00855 
00856 
00857 int
00858 DirectoryViewer::
00859 etags_first(ViewerManager* vm)
00860 {
00861   // prompt the user for the name of a symbol and then bring up an edit
00862   // session on the file defining that symbol.
00863   
00864   CursorWindow::Dialog d("Find symbol in ETAGS database");
00865      
00866   d += new CursorWindow::Dialog::String("symbol",
00867                                         "Symbol to find",
00868                                         "",
00869                                         40
00870                                        );
00871                                 
00872   d += new CursorWindow::Dialog::Ok("ok", "ok");
00873                         
00874   if(d.popup(vm->window()))
00875     return 0;
00876   
00877   std::string symbol = d.element_value("symbol");
00878      
00879   if(symbol.size() == 0)
00880     return 0;
00881 
00882   // now, see if there is a tag with the given symbol name
00883 
00884   FileName     tagsfile;
00885   std::string  default_tags_path;
00886 
00887   EtagsDB* etags = vm->default_etags_db();
00888 
00889   if(etags && etags->ok())
00890   {
00891     std::string file;
00892     int         line;
00893     std::string matching_text;
00894 
00895     bool rv = etags->find_first(symbol, &file, &line, &matching_text);
00896   
00897     if(rv)
00898     {
00899       Viewer* oldie = vm->find_viewer(file);
00900   
00901       if(oldie)
00902       {
00903         oldie->set_row_col_hint(line-1,0);
00904         vm->activate(oldie);
00905       }
00906       else
00907       {
00908   
00909         Viewer* newbie = vm->edit(file);
00910   
00911         if(newbie)
00912         {
00913           newbie->set_row_col_hint(line-1,0);
00914   
00915           vm->vsplit(newbie, file);
00916   
00917         }
00918         else
00919           vm->active_viewport()->beep();
00920       }
00921   
00922     }
00923     
00924   }
00925   else
00926   {
00927     vm->active_viewport()->beep();
00928   }
00929 
00930   return 0;   
00931 }
00932 
00933 int
00934 DirectoryViewer::
00935 cpptags_first(ViewerManager* vm)
00936 {
00937 
00938   CppTagDB::Info* cpptags=(vm->default_cpptags_db());  // pts to static object
00939 
00940   if(!cpptags)
00941   {
00942     // error message will have been handled by ViewerManager code
00943     return 0;
00944   }
00945   
00946   
00947   // prompt the user for the name of a symbol and then bring up an edit
00948   // session on the file defining that symbol.
00949   
00950   CursorWindow::Dialog d("Find symbol in TAGPP.tagpp database");
00951      
00952   d += new CursorWindow::Dialog::String("symbol",
00953                                         "Symbol to find",
00954                                         "",
00955                                         40
00956                                        );
00957                                 
00958   d += new CursorWindow::Dialog::Ok("ok", "ok");
00959                         
00960   if(d.popup(vm->window()))
00961     return 0;
00962   
00963   std::string symbol = d.element_value("symbol");
00964      
00965   if(symbol.size() == 0)
00966     return 0;
00967 
00968   // now, see if there is a tag with the given symbol name
00969 
00970   {
00971     std::string file;
00972     int         line;
00973     std::string matching_text;
00974 
00975     std::vector<cxxtls::CppTagDB::SymbolInfo const *> matches;
00976 
00977     cpptags->findMatchingMembers(symbol, matches);
00978 
00979     if(!matches.empty())
00980     {
00981       // at least one match was found -- save the matches in the global list so that
00982       // we can pop the items off using the ^X , command in the editor or just the , command
00983       // in the directory viewer.
00984 
00985       std::vector<ViewerManager::FileLocation>  locations;
00986       
00987       CXXTLS_FOREACH(CppTagDB::SymbolInfo const *cur, matches)
00988       {
00989          locations.push_back( ViewerManager::FileLocation(cur->file_, cur->line_) );
00990       }
00991 
00992       vm->setFileLocations(locations);
00993 
00994       ViewerManager::FileLocation tmp;
00995 
00996       vm->popFileLocation(tmp);
00997 
00998       file = tmp.filename_;
00999       line = tmp.lineNumber_;
01000 
01001 
01002       Viewer* oldie = vm->find_viewer(file);
01003   
01004       if(oldie)
01005       {
01006         oldie->set_row_col_hint(line-1,0);
01007         vm->activate(oldie);
01008       }
01009       else
01010       {
01011   
01012         Viewer* newbie = vm->edit(file);
01013   
01014         if(newbie)
01015         {
01016           newbie->set_row_col_hint(line-1,0);
01017   
01018           vm->vsplit(newbie, file);
01019   
01020         }
01021         else
01022           vm->active_viewport()->beep();
01023       }
01024   
01025     }
01026     
01027   }
01028 
01029   return 0;   
01030 }
01031 
01032 
01033 int
01034 DirectoryViewer::
01035 etags_all(ViewerManager* vm)
01036 {
01037   // prompt the user for the name of a symbol and then let the user select
01038   // from all symbols matching that one in the etags database.
01039   
01040   CursorWindow::Dialog d("Find all matching symbols in ETAGS database");
01041      
01042   d += new CursorWindow::Dialog::String("symbol",
01043                                         "Symbol to find",
01044                                         "",
01045                                         40
01046                                        );
01047                                 
01048   d += new CursorWindow::Dialog::Ok("ok", "ok");
01049                         
01050   if(d.popup(vm->window()))
01051     return 0;
01052   
01053   std::string symbol = d.element_value("symbol");
01054      
01055   if(symbol.size() == 0)
01056     return 0;
01057 
01058   // now, see if there is a tag with the given symbol name
01059 
01060   FileName     tagsfile;
01061   std::string  default_tags_path;
01062 
01063   EtagsDB* etags = vm->default_etags_db();
01064 
01065   if(etags && etags->ok())
01066   {
01067     std::string file;
01068     int         line;
01069     std::string matching_text;
01070 
01071     bool rv = etags->find_first(symbol, &file, &line, &matching_text);
01072   
01073     if(rv)
01074     {
01075 
01076       CursorWindow::Selection s("Symbols matching " + symbol);
01077     
01078       s += "";
01079 
01080       while(rv)
01081       {
01082          std::string tmp = file;
01083 
01084          char buffer[40];
01085 
01086          snprintf(buffer, 40, ":%d", line);
01087 
01088          tmp += buffer;
01089          tmp += ' ';
01090          tmp += matching_text;
01091 
01092          s += tmp;
01093 
01094          rv = etags->find_next(&file, &line, &matching_text);
01095 
01096       }
01097 
01098       s += "";
01099 
01100       s += "Press Enter to continue";
01101 
01102       if(!s.popup(vm->window()))
01103       {
01104           size_t colon = s.selection_.find_first_of(':');
01105 
01106           if(colon >= s.selection_.size())
01107           {
01108              vm->active_viewport()->beep();
01109              return 0;
01110           }
01111 
01112           file = s.selection_.substr(0, colon);
01113 
01114           std::string tmp = s.selection_.substr(colon+1, s.selection_.size() - colon -1);
01115 
01116           line = 0;
01117 
01118           sscanf(tmp.c_str(), "%d", &line);
01119 
01120           Viewer* oldie = vm->find_viewer(file);
01121           
01122           if(oldie)
01123           {
01124             oldie->set_row_col_hint(line-1,0);
01125             vm->activate(oldie);
01126           }
01127           else
01128           {
01129           
01130             Viewer* newbie = vm->edit(file);
01131           
01132             if(newbie)
01133             {
01134               newbie->set_row_col_hint(line-1,0);
01135           
01136               vm->vsplit(newbie, file);
01137           
01138             }
01139             else
01140               vm->active_viewport()->beep();
01141           }
01142       }
01143   
01144     }
01145     
01146   }
01147   else
01148   {
01149     vm->active_viewport()->beep();
01150   }
01151 
01152   return 0;   
01153 }
01154 
01155 int
01156 DirectoryViewer::
01157 cpptags_all(ViewerManager* vm)
01158 {
01159 
01160   CppTagDB::Info* cpptags=(vm->default_cpptags_db());  // pts to static object
01161 
01162 
01163   if(!cpptags)
01164   {
01165     // error message will have been handled by ViewerManager code
01166     return 0;
01167   }
01168   
01169   
01170   // prompt the user for the name of a symbol and then let the user select
01171   // from all symbols matching that one in the etags database.
01172   
01173   CursorWindow::Dialog d("Find all matching symbols in TAGPP.tagpp database");
01174      
01175   d += new CursorWindow::Dialog::String("symbol",
01176                                         "Symbol to find",
01177                                         "",
01178                                         40
01179                                        );
01180                                 
01181   d += new CursorWindow::Dialog::Ok("ok", "ok");
01182                         
01183   if(d.popup(vm->window()))
01184     return 0;
01185   
01186   std::string symbol = d.element_value("symbol");
01187      
01188   if(symbol.size() == 0)
01189     return 0;
01190 
01191 
01192   std::vector<cxxtls::CppTagDB::SymbolInfo const *> matches;
01193 
01194 
01195   cpptags->findMatchingMembers(symbol, matches, false);  // insensitive comparison
01196 
01197 
01198   if(!matches.empty())
01199   {
01200     std::string file;
01201     int         line;
01202 
01203     {
01204 
01205       CursorWindow::Selection s("Symbols matching " + symbol);
01206     
01207       s += "";
01208 
01209       
01210       std::vector<cxxtls::CppTagDB::SymbolInfo const *>::const_iterator first, last;
01211 
01212       for(first = matches.begin(), last = matches.end(); first != last; ++first)
01213       {
01214          std::string tmp = (*first)->file_;
01215 
01216          char buffer[40];
01217 
01218          snprintf(buffer, 40, ":%d", (*first)->line_);
01219 
01220          tmp += buffer;
01221          tmp += ' ';
01222 
01223          s += tmp;
01224 
01225 
01226       }
01227 
01228       s += "";
01229 
01230       s += "Press Enter to continue";
01231 
01232       if(!s.popup(vm->window()))
01233       {
01234           size_t colon = s.selection_.find_first_of(':');
01235 
01236           if(colon >= s.selection_.size())
01237           {
01238              vm->active_viewport()->beep();
01239              return 0;
01240           }
01241 
01242           file = s.selection_.substr(0, colon);
01243 
01244           std::string tmp = s.selection_.substr(colon+1, s.selection_.size() - colon -1);
01245 
01246           line = 0;
01247 
01248           sscanf(tmp.c_str(), "%d", &line);
01249 
01250           Viewer* oldie = vm->find_viewer(file);
01251           
01252           if(oldie)
01253           {
01254             oldie->set_row_col_hint(line-1,0);
01255             vm->activate(oldie);
01256           }
01257           else
01258           {
01259           
01260             Viewer* newbie = vm->edit(file);
01261           
01262             if(newbie)
01263             {
01264               newbie->set_row_col_hint(line-1,0);
01265           
01266               vm->vsplit(newbie, file);
01267           
01268             }
01269             else
01270               vm->active_viewport()->beep();
01271           }
01272       }
01273   
01274     }
01275     
01276   }
01277   else
01278   {
01279     vm->active_viewport()->beep();
01280   }
01281 
01282   return 0;   
01283 }
01284 
01285 int
01286 DirectoryViewer::
01287 cpptagviewer(ViewerManager* vm)
01288 {
01289     CursorWindow::Dialog m("Scan Subdirectories for C++ symbols?");
01290      
01291     m += new CursorWindow::Dialog::Ok("Begin Scan?","ok");
01292 
01293    if(m.popup(vm->window()))
01294        return 0;  // user aborted
01295     
01296     
01297     {
01298         std::string file = fullname_;
01299 
01300         if(file.size() > 2)
01301         {
01302            file = file.substr(0, file.size() -2); // remove trailing /*
01303         }
01304 
01305         file += SLASH;
01306 
01307 
01308         file += "!.cpptagdb";
01309 
01310 
01311         Viewer* oldie = vm->find_viewer(file);
01312         
01313         if(oldie)
01314         {
01315           vm->activate(oldie);
01316         }
01317         else
01318         {
01319         
01320           Viewer* newbie = vm->open(file);
01321         
01322           if(newbie)
01323           {
01324             vm->hsplit(newbie, file);
01325         
01326           }
01327           else
01328             vm->active_viewport()->beep();
01329         }
01330     }
01331 
01332   return 0;   
01333 }
01334 
01335 
01336 int
01337 DirectoryViewer::
01338 copy_files(ViewerManager*vm)
01339   {
01340     if(marks_.begin() == marks_.end())
01341       return 0;
01342 
01343     FileName dirname  = fullname_.dirname();
01344 
01345     FileName target;
01346 
01347     CursorWindow::FileSelector d("Copy files to a directory", fullname_ + "*", "");
01348 
01349     target = d.popup(vm->window(),0); 
01350 
01351     if(target.size() == 0)
01352       return 0;
01353 
01354     if(target[0] != '/' && target[1] != ':')
01355           {
01356             target = dirname + target;
01357           }
01358 
01359     target.convert_to_absolute_path();
01360 
01361     if(target.exists() && !target.is_dir())
01362     {
01363 
01364       CursorWindow::Message m("Error");
01365 
01366       m += "Sorry, target of a multifile copy operaton";
01367       m += "must be a directory.";
01368       m += "";
01369       m += "Press enter to continue";
01370                         
01371       m.popup(vm->window());
01372       return 0;
01373         
01374     }
01375 
01376     if(target[target.size()-1] != '/')
01377       target += '/';
01378 
01379     if(target == fullname_.dirname())
01380     {
01381         
01382       CursorWindow::Message m("Error");
01383 
01384       m += "Can't copy multiple files to the current directory";
01385       m += "";
01386       m += "Press enter to continue";
01387                         
01388       m.popup(vm->window());
01389       return 0;
01390         
01391     }
01392 
01393     marked_files_set::iterator first = marks_.begin(),
01394                                last  = marks_.end();
01395                         
01396                         
01397     while(first != last)
01398     {
01399       FileName source = fullname_.dirname() + *first;
01400       FileName dest   = target + *first;
01401 
01402       if(source.copy(dest))
01403       {
01404         int errtype = errno;
01405 
01406         std::string ErrorText("Error -- press Esc to cancel or Enter to continue");
01407 
01408         
01409         {
01410           char const *errtext = strerror(errtype);
01411 
01412           ErrorText="Copy Error (";
01413           ErrorText += errtext;
01414           ErrorText += " -- press Esc to cancel or Enter to continue";
01415         }
01416 
01417 
01418         
01419         CursorWindow::Dialog e(ErrorText.c_str());
01420         
01421         e += new CursorWindow::Dialog::Ok("name",
01422                                       "error copying " + (std::string&)(*first)
01423                                          );
01424                         
01425         if(e.popup(vm->window()))
01426           return 0;
01427         
01428       }
01429 
01430       ++first;
01431 
01432     }
01433 
01434     return 1;
01435 
01436   }
01437 
01438 
01439 int
01440 DirectoryViewer::
01441 delete_file(size_t index, ViewerManager* vm, bool verify)
01442   {
01443     // allow the user to delete the file under the cursor.
01444     //
01445     // If the file was not actually deleted, return 1.  Otherwise return 0
01446 
01447     if(index < names_.size())
01448     {
01449       FileName filename = fullname_.dirname() + std::string("/") + names_[index];
01450 
01451       {
01452         if(verify)
01453         {
01454           CursorWindow::Dialog d("Delete file (press Esc to cancel)");
01455         
01456           d += new CursorWindow::Dialog::String("name",
01457                                             std::string("delete file ") + names_[index] + " ?",
01458                                             "    ",
01459                                             1
01460                                            );
01461                                 
01462           if(d.popup(vm->window()))
01463             return 0;
01464         }
01465         
01466         FileName target = fullname_.dirname() + std::string("/") + names_[index];
01467 
01468         bool deleteFailed;
01469 
01470         if(target.is_dir())
01471           deleteFailed = target.rmdir();
01472         else
01473           deleteFailed = target.remove();
01474 
01475 
01476         if(deleteFailed)
01477         {
01478           CursorWindow::Message m(std::string("Error deleting file '") + names_[index] + std::string("'"));
01479         
01480           m += "Couldn't delete " + names_[index];
01481           m += "                                         ";
01482           m += "Press enter to continue";
01483                                 
01484           m.popup(vm->window());
01485           return 1;
01486         }
01487 
01488         remove_item(index);
01489         return 0;
01490 
01491         
01492         
01493       }
01494     }
01495     return 0;
01496 
01497   }
01498 
01499 
01500 int
01501 DirectoryViewer::
01502 change_mode(size_t index, ViewerManager* vm)
01503 {
01504   using namespace std;
01505 
01506   // allow the user to edit file attributes of the file under the cursor.
01507   if(index < names_.size())
01508   {
01509     FileName filename = fullname_.dirname() + names_[index];
01510 
01511     string userPerms;
01512     string groupPerms;
01513     string worldPerms;
01514 
01515     FileMode extantMode = filename.file_mode();
01516 
01517     extantMode.unpackPermissions(userPerms, groupPerms, worldPerms);
01518 
01519 
01520     CursorWindow::Dialog d(string( "Change file " + names_[index] + " permissions" ) );
01521 
01522     d += new CursorWindow::Dialog::String("World",
01523                                           "World Permissions",
01524                                           worldPerms,
01525                                           4
01526                                          );
01527 
01528     d += new CursorWindow::Dialog::String("Group",
01529                                           "Group permissions",
01530                                           groupPerms,
01531                                           4
01532                                          );
01533 
01534     d += new CursorWindow::Dialog::String("User",
01535                                           "User permissions",
01536                                           userPerms,
01537                                           4
01538                                          );
01539 
01540     d.set_first_input_field("User");
01541 
01542     string group, world, user; // user inputs
01543 
01544     bool done=false;
01545 
01546     while(!done)
01547     {
01548 
01549       if(d.popup(vm->window()))
01550         return 0;
01551       
01552       group = d.element_value("Group"),
01553       world = d.element_value("World"),
01554       user  = d.element_value("User");
01555       
01556       string failure;  // name of failing perm field
01557       
01558       if(!extantMode.permStringValid(user))  failure="User";
01559       if(!extantMode.permStringValid(group)) failure="Group";
01560       if(!extantMode.permStringValid(world)) failure="World";
01561       
01562       if(!failure.empty())
01563       {
01564         CursorWindow::Message m("Error:");
01565       
01566         m += failure + " permission string is invalid!";
01567                               
01568         m.popup(vm->window());
01569 
01570         d.set_first_input_field(failure);
01571 
01572       }
01573       else
01574         done = true;
01575 
01576     }
01577 
01578     // all fields pass muster
01579 
01580     extantMode.packPermissions(user, group, world);
01581     
01582     if( filename.chmod(extantMode) != 0 )
01583     {
01584       CursorWindow::Message m("Error:");
01585     
01586       m += "chmod failed on " + names_[index];
01587                             
01588       m.popup(vm->window());
01589       return 0;
01590     }
01591       
01592     filename.file_stat(&status_[index]);
01593       
01594     generate_row_text(index);
01595     
01596     return 1;
01597 
01598   }
01599 
01600   return 0;
01601 
01602 }
01603 
01604 
01605 void
01606 DirectoryViewer::
01607 view_file_or_dir(std::string const &dir, ViewerManager* vm, bool is_dir)
01611   {
01612 
01613     Viewer *newbie = vm->find_viewer(dir);
01614 
01615     if(newbie)
01616     {
01617       vm->activate(newbie);
01618     }
01619     else
01620     if(is_dir)
01621     {
01622 
01623       newbie = new ListViewer(new DirectoryViewer(dir,
01624                                                 user_names_,
01625                                                 show_ids_),
01626                                                 vm
01627                              );
01628 
01629       vm->add( newbie, dir);
01630     }
01631     else
01632     {
01633       newbie = vm->open(dir);
01634 
01635       if(newbie)
01636         vm->add(newbie, dir);
01637     }
01638         
01639   }
01640 
01641 void
01642 DirectoryViewer::
01643 view_dir(size_t index, ViewerManager* vm)
01644   {
01645     if(names_.size() <= index)
01646       return;  // no target object
01647 
01648     // popup a new browser
01649 
01650     FileName dir = fullname_.dirname() + names_[index];
01651 
01652     if(names_[index] != std::string(".") && dir.is_dir())
01653     {
01654 
01655       dir.convertToDirectorySearchPattern();
01656 
01657       dir.convert_to_absolute_path();
01658 
01659       view_file_or_dir(dir,vm,true);
01660 
01661     }
01662     else
01663     {
01664       view_file_or_dir(dir, vm, false);
01665     }
01666         
01667   }
01668 
01669 int
01670 DirectoryViewer::
01671 mark_files_by_pattern(ViewerManager* vm)
01672     // prompt the user for a file name pattern and mark files whose names
01673     // match that pattern.
01674   {
01675     CursorWindow::Dialog d("Mark multiple files");
01676 
01677     d += new CursorWindow::Dialog::String("name",
01678                                           "Name pattern",
01679                                           "*",
01680                                           40
01681                                          );
01682                                 
01683     if(d.popup(vm->window()))
01684       return 0;
01685 
01686     std::string pattern = d.element_value("name");
01687 
01688     if(pattern == "")
01689       return 0;
01690 
01691 
01692     int count=0;
01693 
01694     {
01695       file_name_vector::iterator first = names_.begin(),
01696                                  last  = names_.end();
01697         
01698         
01699       while(first != last)
01700       {
01701         FileName const& curname = *first++;
01702 
01703         if(curname.matches(pattern))
01704         {
01705           ++count;  // count of changes, not marks
01706         
01707           marked_files_set::iterator scan = marks_.find(curname);
01708         
01709           if(scan != marks_.end())
01710             marks_.erase(scan);
01711           else
01712             marks_.insert(curname);
01713         }
01714 
01715       }
01716     }
01717 
01718     if(count == 0)
01719       return 0;
01720 
01721     return 1;
01722 
01723   }
01724 
01725 
01726 int
01727 DirectoryViewer::
01728 delete_files(ViewerManager* vm)
01729   {
01730     if(marks_.begin() == marks_.end())
01731       return 0;
01732 
01733     {
01734       CursorWindow::Dialog d("Delete marked files (press Esc to cancel)");
01735 
01736       d += new CursorWindow::Dialog::String("name",
01737                                         std::string("delete files"),
01738                                         "    ",
01739                                         1
01740                                        );
01741                         
01742       if(d.popup(vm->window()))
01743         return 0;
01744     }
01745 
01746 
01747     size_t i,
01748            final = names_.size(),
01749            count = 0;
01750 
01751     for(i=0; i < final;)
01752     {
01753       if(marks_.find(names_[i]) != marks_.end())
01754       {
01755         // this item is marked
01756 
01757         if(delete_file(i, vm, false))
01758           ++i;  // file didn't get removed from the list and didn't get deleted
01759         
01760         ++count;
01761         
01762         // don't increment i, names_[i] was just deleted (supposedly)
01763         
01764         final = names_.size();
01765         
01766       }
01767       else
01768         ++i;  // skip this guy
01769     }
01770 
01771     if(count)
01772       return 1;
01773 
01774     return 0;
01775   }
01776 
01777 
01778 Viewer*
01779 DirectoryViewer::
01780 app(ViewerManager*vm, std::string &fullname)
01781 {
01782   if(fullname.size() == 0)
01783   {
01784 
01785     // do not use the viewer selector from here because it can not repaint the screen
01786     // in this context
01787 
01788     CursorWindow::Dialog d("File or Directory name");
01789 
01790     d += new CursorWindow::Dialog::String("name",
01791                                           "path",
01792                                           "*",
01793                                           40
01794                                          );
01795                                 
01796     if(d.popup(vm->window()))
01797       return 0;
01798 
01799     fullname = d.element_value("name");
01800 
01801     if(fullname == "")
01802       return 0;
01803 
01804 
01805     FileName tmp(fullname);
01806     tmp.convert_to_absolute_path();
01807 
01808     fullname = tmp;
01809 
01810   }
01811 
01812   DirectoryViewer *com = new DirectoryViewer(fullname);
01813 
01814   return new ListViewer(com,vm);
01815 }
01816 
01817 
01818 int
01819 DirectoryViewer::
01820 rename_file(size_t index, ViewerManager* vm, FileName target_filename)
01821   {
01822     // allow the user to rename the file under the cursor.  Return 0 or 1
01823     // based on whether the target of the rename lies in the current directory.
01824 
01825     if(index < names_.size())
01826     {
01827       static std::string sepcharString;
01828 
01829       static char sepchar= '/';
01830 
01831       if(sepcharString.empty())
01832          sepcharString += '/';
01833 
01834 
01835       FileName dirname  = fullname_.dirname();
01836       FileName filename = dirname + sepcharString + names_[index];
01837 
01838       {
01839         FileName target;
01840         
01841         if(target_filename == "")
01842         {
01843           CursorWindow::FileSelector d("Rename file:", fullname_ + "*", "");
01844 
01845           target = d.popup(vm->window(),0);
01846 
01847           if(target.size() == 0)
01848             return 0;
01849         
01850           if(!target.is_absolute_path())
01851           {
01852               target = dirname + target;
01853           }
01854         }
01855         else
01856           target = target_filename;
01857         
01858         if(target.is_dir())
01859         {
01860           target += sepchar;
01861           target += names_[index];
01862         }
01863         
01864         if(target.exists())
01865         {
01866         
01867           CursorWindow::Dialog e("Replace file? (Press Esc to cancel)");
01868         
01869           e += new CursorWindow::Dialog::Ok("name",
01870                                             std::string("Replace file ") + target
01871                                            );
01872           if(e.popup(vm->window()))
01873             return 0;
01874         }
01875         
01876         if(target == filename)
01877         {
01878           return 0;  // nothing to do
01879         }
01880         
01881         if(filename.rename(target))
01882         {
01883           // error occurred while renaming
01884         
01885         
01886           CursorWindow::Message  e("Error");
01887         
01888           e += "Error renaming: " + names_[index];
01889                                 
01890           e.popup(vm->window());
01891           return 0;
01892         
01893         }
01894         
01895         {
01896           // unmark the old name
01897         
01898           marked_files_set::iterator scan = marks_.find(target.basename());
01899         
01900           if(scan != marks_.end())
01901             marks_.erase(scan);
01902         
01903         }
01904         
01905         remove_item(index);
01906         
01907         if(target.dirname() == dirname)
01908         {
01909           read_directory();
01910           generate_row_text();
01911         
01912           return 1;
01913         }
01914         
01915       }
01916     }
01917     return 0;
01918 
01919   }
01920 
01921 
01922 int
01923 DirectoryViewer::
01924 rename_files(ViewerManager*vm)
01925   {
01926     if(marks_.begin() == marks_.end())
01927       return 0;
01928 
01929 
01930     FileName target;
01931 
01932 
01933     CursorWindow::FileSelector d("Rename files to directory", fullname_ + "*", "");
01934 
01935     target = d.popup(vm->window(), 0);
01936 
01937     if(target.size() == 0)
01938       return 0;
01939 
01940     target.convert_to_absolute_path();
01941 
01942     if(target.exists() && !target.is_dir())
01943     {
01944 
01945       CursorWindow::Message e("Error");
01946 
01947       e += "Target of a multi-file rename must be a diretory";
01948       e += "";
01949       e += "Press enter to continue";
01950                         
01951       e.popup(vm->window());
01952       return 0;
01953         
01954     }
01955 
01956     if(target[target.size()-1] != '/')
01957       target += '/';
01958 
01959     if(target == fullname_.dirname())
01960     {
01961         
01962       CursorWindow::Message e("Error");
01963 
01964       e += "Can't rename multiple files to the current directory";
01965       e += "";
01966       e += "Press enter to continue";
01967                         
01968       e.popup(vm->window());
01969       return 0;
01970         
01971     }
01972 
01973     marked_files_set::iterator first = marks_.begin(),
01974                                last  = marks_.end();
01975                         
01976                         
01977     while(first != last)
01978     {
01979       FileName source = fullname_.dirname() + *first;
01980       FileName dest   = target + *first;
01981 
01982       if(source.rename(dest))
01983       {
01984         
01985         CursorWindow::Dialog e("Error -- press Esc to cancel or Enter to continue");
01986         
01987         e += new CursorWindow::Dialog::Ok("name",
01988                                       "error renaming " + (std::string&)(*first)
01989                                          );
01990                         
01991         if(e.popup(vm->window()))
01992           return 0;
01993         
01994       }
01995 
01996       ++first;
01997 
01998     }
01999 
02000     // Renamed files no longer exist in the directory display but may
02001     // exit in the directory -- under different names.  A re-read of
02002     // the directory display needs to be done.
02003 
02004     read_directory();
02005 
02006     generate_row_text();
02007 
02008     return 1;
02009 
02010   }
02011 
02012 
02013 std::auto_ptr< std::list<std::string> >
02014 DirectoryViewer::
02015 help_text()
02016 {
02017   std::list< std::string > *rv = new std::list<std::string>;
02018 
02019   rv->push_back("");
02020   rv->push_back("");
02021   rv->push_back("The DirectoryViewer");
02022   rv->push_back("");
02023   rv->push_back("(Use ^S to search)");
02024   rv->push_back("");
02025   rv->push_back("List the files in a directory and allow the user to issue");
02026   rv->push_back("commands that view them, edit them, discover information");
02027   rv->push_back("about them, etc.");
02028   rv->push_back("");
02029   rv->push_back("Here are the key bindings:");
02030   rv->push_back("");
02031   rv->push_back("  Enter -- view the file under the cursor");
02032   rv->push_back("  .  -- find a symbol in the TAGPP.tagpp database (see below)");
02033   rv->push_back("  /  -- find all matching symbols in TAGPP.tagpp database");
02034   rv->push_back("  !  -- find symbol in ETAGS database");
02035   rv->push_back("        Note:  the ETAGSPATH variable must be set for ETAGS commands to work.  ");
02036   rv->push_back("               See the editor's help for a description of it.");
02037   rv->push_back("  ?  -- find all matching symbols in ETAGS database");
02038   rv->push_back("  ^  -- view the parent directory");
02039   rv->push_back("  \\  -- display a symbolic link file's target");
02040   rv->push_back("  0  -- view symbols in this subdir tree");
02041   rv->push_back("  a  -- modify file attributes");
02042   rv->push_back("  c  -- copy the file under the cursor");
02043   rv->push_back("  C  -- copy marked files");
02044   rv->push_back("  d  -- delete the file under the cursor");
02045   rv->push_back("  D  -- delete marked files");
02046   rv->push_back("  e  -- edit the file/directory under the cursor");
02047   rv->push_back("  i  -- toggle display of user/group ids");
02048   rv->push_back("  l  -- re-read the directory and sort by name");
02049   rv->push_back("  L  -- re-read the directory and sort by SIZE");
02050   rv->push_back("  m  -- mark the current file");
02051   rv->push_back("  F5 -- function key 5 marks the current file");
02052   rv->push_back("  M  -- mark files matching a filename pattern");
02053   rv->push_back("  r  -- rename the current file");
02054   rv->push_back("  R  -- rename marked files");
02055   rv->push_back("  s  -- view the file without editing it");
02056   rv->push_back("  t  -- re-read the directory and sort by DATE");
02057   rv->push_back("  u  -- toggle user/group names display");
02058   rv->push_back("  V  -- Run a TableCommander script -- ");
02059   rv->push_back("        see ~/.tools_home/stv/*.sh for available scripts");
02060   rv->push_back("");
02061   rv->push_back("The TAGPP.tagpp database is a program symbol database created");
02062   rv->push_back("by the makeCppTags script found in the 'scripts' directory");
02063   rv->push_back("in this distribution.");
02064 
02065 
02066   return std::auto_ptr< std::list<std::string> >(rv);
02067 }
02068 
02069 
02070 bool DirectoryViewer::fetchAllLines(std::list< std::string > &output )
02071 {
02072 
02073    CXXTLS_FOREACH(FileName const &cur, names_)
02074        output.push_back(cur);
02075 
02076    return true;
02077 }
02078 
02079 
02080 } // namespace cxxtls
Generated on Wed Feb 29 22:50:04 2012 for CXXUtilities by  doxygen 1.6.3