00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00030
00031
00032 #include <cxxtls/viewermanager.h>
00033 #include <cxxtls/file.h>
00034 #include <cxxtls/options.h>
00035 #include <cxxtls/etagsdb.h>
00036 #include <cxxtls/strtool.h>
00037 #include <cxxtls/cursesinterface.h>
00038 #include <cxxtls/user.h>
00039 #include <cxxtls/cpptagdb.h>
00040 #include <cxxtls/strtool.h>
00041 #include <cxxtls/foreach.h>
00042
00043 #include <stdlib.h>
00044 #include <portable_io.h>
00045 #include <fstream>
00046 #include <iomanip>
00047
00048 using namespace std;
00049
00050 namespace cxxtls
00051 {
00052
00053 static int trash;
00054
00055 typedef CursorWindow::viewport::repaint_handler repaint_handler;
00056
00057 int ViewerManager::normal_att = CursorWindow::normal;
00058 int ViewerManager::active_title_att = CursorWindow::reverse_bold;
00059 int ViewerManager::inactive_title_att= CursorWindow::underlined;
00060 int ViewerManager::active_mark_att = CursorWindow::reverse_ul;
00061 int ViewerManager::inactive_mark_att = CursorWindow::bold;
00062 int ViewerManager::bottom_att = CursorWindow::underlined;
00063 int ViewerManager::highlighted_att = CursorWindow::reversed;
00064
00065
00066 class ViewerSelector
00067
00071
00072 : public Viewer
00073 {
00074 public:
00075
00076 size_t cur_row_;
00077 size_t display_top_;
00078 int first_row_;
00079 bool active_;
00080
00081 ViewerSelector(ViewerManager* m)
00082 : Viewer(m),
00083 cur_row_(0),
00084 display_top_(0),
00085 first_row_(2),
00086 active_(true)
00087 {
00088 trash=2;
00089 }
00090
00091 void operator() ( CursorWindow::viewport * vp,int cmd);
00093
00094 bool handle_event( CursorWindow::input_event const * e,
00095 CursorWindow::viewport * vp
00096 );
00097
00098 static string app_name;
00099
00100 string const &application_name() const { return app_name; }
00101
00102 void repaint(CursorWindow::viewport *vp)
00103 {
00104 (*this)(vp, activate );
00105 }
00106
00107 void output_row_text(CursorWindow::viewport * vp, int i)
00108 {
00109
00110
00111
00112 int maxw = vp->size().col_ - 15;
00113
00114 if(i < (int)manager_->viewers_.size() )
00115 {
00116 string tmp = manager_->viewers_[i].first->application_name();
00117
00118 if(tmp.size() > 10)
00119 tmp.erase(10,tmp.size());
00120
00121 Viewer* viewer = manager_->viewers_[i].first;
00122
00123 FileName thisfile(viewer->description());
00124
00125 *vp << (viewer->is_dirty() ? "*" : " ")
00126 << std::setw(10) << tmp
00127 << " " << thisfile.shorten(maxw)
00128 ;
00129 }
00130 }
00131
00132 string description() const
00133 {
00134 return "Lets you choose a viewer";
00135 }
00136 };
00137
00138 string ViewerSelector::app_name("ViewrSelct");
00139
00140
00141 ViewerManager::
00142 ViewerManager()
00143 : active_viewport_(0),
00144 vs_(0),
00145 override_active_viewport_(10000),
00146 dir_opener_(0)
00147 {
00148 setup_key_bindings();
00149
00150 vs_.reset(new ViewerSelector(this));
00151
00152 ViewerManager::normal_att = CursorWindow::normal_att;
00153 ViewerManager::active_title_att = CursorWindow::active_title_att;
00154 ViewerManager::inactive_title_att= CursorWindow::inactive_title_att;
00155 ViewerManager::active_mark_att = CursorWindow::active_mark_att;
00156 ViewerManager::inactive_mark_att = CursorWindow::inactive_mark_att;
00157 ViewerManager::bottom_att = CursorWindow::bottom_att;
00158 ViewerManager::highlighted_att = CursorWindow::highlighted_att;
00159
00160
00161 }
00162
00163 ViewerManager::
00164 ~ViewerManager()
00165 {
00166
00167
00168 vector<viewport*>::iterator vp_next = viewports_.begin(),
00169 vp_last = viewports_.end();
00170
00171 while(vp_next != vp_last)
00172 {
00173 viewport* entry = *vp_next++;
00174
00175 delete entry;
00176
00177 }
00178
00179 vector<vpentry>::iterator vr_next = viewers_.begin(),
00180 vr_last = viewers_.end();
00181
00182 while(vr_next != vr_last)
00183 {
00184 vpentry &entry = *vr_next++;
00185
00186 delete entry.first;
00187
00188 }
00189
00190
00191 }
00192
00193 void
00194 ViewerManager::
00195 open()
00196 {
00197 UserInfo me = UserInfo::get();
00198
00199 FileName tooldir = me.home_dir_ + "/.tools_home";
00200
00201 tool_dir_ = tooldir;
00202
00203 cw_.open();
00204 }
00205
00206 void
00207 ViewerManager::
00208 close()
00209 {
00210 cw_.close();
00211 }
00212
00213 static bool jump2dir=false;
00214
00215
00216
00217
00218
00219
00220 void
00221 ViewerManager::
00222 recordExitDir() const
00223 {
00224 if(jump2dir && exit_dir_.size())
00225 {
00226 FileName exitFileName( tool_dir_ + "/exitDir.txt" );
00227
00228 ofstream exitFile(exitFileName.c_str());
00229
00230 exitFile << exit_dir_ << endl;
00231 }
00232 }
00233
00234 void
00235 ViewerManager::
00236 exit()
00237 {
00238 cw_.close();
00239
00240 recordExitDir();
00241
00242 ::exit(0);
00243 }
00244
00245
00246 void
00247 ViewerManager::
00248 add(Viewer* v, string fullname)
00249 {
00250
00251
00252
00253 vector<vpentry>::iterator first = viewers_.begin(),
00254 last = viewers_.end();
00255
00256 while(first != last)
00257 {
00258 vpentry &entry = *first++;
00259
00260 if(entry.first == v)
00261 {
00262 break;
00263 }
00264
00265 }
00266
00267 if(first == last)
00268 {
00269
00270
00271 viewers_.push_back( vpentry(v, fullname) );
00272
00273 }
00274
00275 activate(v);
00276
00277
00278 }
00279
00280
00281
00282
00283 bool
00284 ViewerManager::
00285 activate(Viewer* v)
00286 {
00287
00288 vector<viewport*>::iterator vp_next = viewports_.begin(),
00289 vp_last = viewports_.end();
00290
00291 size_t count = 0;
00292
00293 while(vp_next != vp_last)
00294 {
00295 viewport* entry = *vp_next++;
00296
00297 repaint_handler *rh = entry->get_repaint_handler();
00298
00299 Viewer* vp = dynamic_cast<Viewer*>(rh);
00300
00301 if(vp == v)
00302 {
00303
00304
00305
00306 entry->activate();
00307 override_active_viewport_ = count;
00308
00309 std::string viewerName = find_viewer_name(vp);
00310
00311 order_.activate( viewerName );
00312
00313 return false;
00314
00315
00316 }
00317
00318 ++count;
00319
00320 }
00321
00322
00323
00324
00325
00326 vector<vpentry>::iterator vr_next = viewers_.begin(),
00327 vr_last = viewers_.end();
00328
00329 while(vr_next != vr_last)
00330 {
00331 vpentry &entry = *vr_next;
00332
00333 if(entry.first == v)
00334 break;
00335
00336 ++vr_next;
00337
00338 }
00339
00340 if(vr_next != vr_last)
00341 {
00342
00343
00344
00345 if(active_viewport_ >= viewports_.size())
00346 {
00347 viewports_.push_back(cw_.new_viewport(v).release());
00348 active_viewport_ = viewports_.size() -1;
00349 }
00350 else
00351 viewports_[active_viewport_]->set_repaint_handler(v);
00352
00353 viewports_[active_viewport_]->activate();
00354
00355 repaint_handler *rh = viewports_[active_viewport_]->get_repaint_handler();
00356
00357 Viewer* vp = dynamic_cast<Viewer*>(rh);
00358
00359 std::string viewerName = find_viewer_name(vp);
00360
00361 order_.activate( viewerName );
00362
00363 return false;
00364
00365 }
00366
00367
00368 return true;
00369 }
00370
00371 void
00372 ViewerManager::
00373 vsplit(Viewer* v, string fullname)
00374 {
00375
00376
00377
00378 if(viewports_.size())
00379 {
00380
00381
00382
00383
00384
00385 size_t i;
00386
00387 for(i=0; i < viewports_.size(); ++i)
00388 {
00389 repaint_handler *rh = viewports_[i]->get_repaint_handler();
00390
00391 Viewer* vp = dynamic_cast<Viewer*>(rh);
00392
00393 if(vp == v)
00394 {
00395
00396
00397 viewports_[i]->activate();
00398 active_viewport_ = i;
00399 return;
00400
00401 }
00402
00403 }
00404
00405
00406
00407
00408
00409 bool found=false;
00410
00411 for(i=0; i < viewers_.size(); ++i)
00412 {
00413 if( viewers_[i].first == v )
00414 {
00415 found = true;
00416 break;
00417 }
00418 }
00419
00420 if(!found)
00421 {
00422
00423
00424 viewers_.push_back( vpentry(v,fullname) );
00425
00426 }
00427
00428
00429
00430
00431
00432 viewports_.push_back( viewports_[active_viewport_]->vsplit(v).release() );
00433
00434 active_viewport_ = viewports_.size()-1;
00435
00436 viewports_[active_viewport_]->activate();
00437
00438 }
00439 }
00440
00441
00442 void
00443 ViewerManager::
00444 hsplit(Viewer* v, string fullname)
00445 {
00446
00447
00448
00449 if(viewports_.size())
00450 {
00451
00452
00453
00454
00455
00456 size_t i;
00457
00458 for(i=0; i < viewports_.size(); ++i)
00459 {
00460 repaint_handler *rh = viewports_[i]->get_repaint_handler();
00461
00462 Viewer* vp = dynamic_cast<Viewer*>(rh);
00463
00464 if(vp == v)
00465 {
00466
00467
00468 viewports_[i]->activate();
00469 active_viewport_ = i;
00470 return;
00471
00472 }
00473
00474 }
00475
00476
00477
00478
00479
00480 bool found=false;
00481
00482 for(i=0; i < viewers_.size(); ++i)
00483 {
00484 if( viewers_[i].first == v )
00485 {
00486 found = true;
00487 break;
00488 }
00489 }
00490
00491 if(!found)
00492 {
00493
00494
00495 viewers_.push_back( vpentry(v,fullname) );
00496
00497 }
00498
00499
00500
00501
00502
00503 viewports_.push_back( viewports_[active_viewport_]->hsplit(v).release() );
00504
00505 active_viewport_ = viewports_.size()-1;
00506
00507 viewports_[active_viewport_]->activate();
00508
00509 }
00510 }
00511
00512
00513 void
00514 ViewerManager::
00515 dispatch_event(ViewerManager::input_event const & event)
00516 {
00517
00518
00519
00520
00521 if(viewports_.size())
00522 {
00523 viewport* port = viewports_[active_viewport_];
00524
00525 repaint_handler* rh = port->get_repaint_handler();
00526
00527 Viewer* r = dynamic_cast<Viewer*>(rh);
00528
00529 if(r->handle_event(&event, port))
00530 {
00531 std::string viewerName = find_viewer_name(r);
00532
00533 order_.discard(viewerName);
00534
00535
00536
00537 viewports_.erase( viewports_.begin() + active_viewport_ );
00538
00539 delete port;
00540
00541
00542
00543 for(size_t i = 0; i < viewers_.size(); ++i)
00544 {
00545 if( viewers_[i].first == r )
00546 {
00547 viewers_.erase(viewers_.begin() + i );
00548 break;
00549 }
00550 }
00551
00552 if(r != vs_.get())
00553 {
00554
00555
00556
00557 delete r;
00558 }
00559
00560 if(viewers_.size() == 0)
00561 {
00562 exit();
00563 }
00564 else
00565 if(viewports_.size() == 0)
00566 {
00567
00568
00569
00570
00571
00572 active_viewport_ = 0;
00573
00574 size_t youngest_viewer = viewers_.size() -1;
00575
00576 MRU<std::string>::iterator mruPtr = order_.mostRecent();
00577
00578 if(mruPtr != order_.end())
00579 {
00580 std::string mru = *mruPtr;
00581
00582 for(size_t i = 0; i < viewers_.size(); ++i)
00583 {
00584 if(mru == viewers_[i].second)
00585 {
00586 youngest_viewer = i;
00587 break;
00588 }
00589 }
00590
00591 }
00592
00593
00594 viewports_.push_back(cw_.new_viewport
00595 ( viewers_[youngest_viewer].first ).release()
00596 );
00597
00598 viewports_[0]->activate();
00599
00600 }
00601
00602 if(override_active_viewport_ < viewports_.size())
00603 {
00604
00605
00606
00607
00608
00609 active_viewport_ = override_active_viewport_;
00610
00611 override_active_viewport_ = 10000;
00612 }
00613
00614
00615 if(active_viewport_ >= viewports_.size() )
00616 {
00617 active_viewport_ = viewports_.size() -1 ;
00618 }
00619
00620
00621
00622 if( (int)(active_viewport_) < 0)
00623 active_viewport_ = 0;
00624
00625 if(viewports_.size())
00626 viewports_[active_viewport_]->activate();
00627
00628 }
00629 else
00630 {
00631 if(override_active_viewport_ < viewports_.size())
00632 {
00633 active_viewport_ = override_active_viewport_;
00634 override_active_viewport_ = 10000;
00635
00636 }
00637 }
00638
00639 }
00640 }
00641
00642 list<string> ViewerManager::key_bindings_doc;
00643
00644 void
00645 ViewerManager::
00646 setup_key_bindings()
00647 {
00648
00649
00650 master_key_map::sequence adder(master_keys_, new_application);
00651 adder += 'X' - '@';
00652 adder += 'N' - '@';
00653 adder.complete();
00654 key_bindings_doc.push_back("^X ^N -- new application covering current viewer");
00655
00656 master_key_map::sequence sheller(master_keys_, interactive_shell);
00657 sheller += 'X' - '@';
00658 sheller += 'Z' - '@';
00659 sheller.complete();
00660 key_bindings_doc.push_back("^X ^Z -- bring up an interactive shell");
00661
00662
00663 master_key_map::sequence addeditor(master_keys_, new_editor);
00664 addeditor += 'X' - '@';
00665 addeditor += 'F' - '@';
00666 addeditor.complete();
00667 key_bindings_doc.push_back("^X ^F -- new editor covering current viewer");
00668
00669 master_key_map::sequence addviewer(master_keys_, new_viewer);
00670 addviewer += 'X' - '@';
00671 addviewer += 'V' - '@';
00672 addviewer.complete();
00673 key_bindings_doc.push_back("^X ^V -- new viewer covering current viewer");
00674
00675 master_key_map::sequence vsplitter(master_keys_, horizontal_split);
00676 vsplitter += 'X' - '@';
00677 vsplitter += '3';
00678 vsplitter.complete();
00679 key_bindings_doc.push_back("^X ^3 -- split viewer horizontally");
00680
00681 master_key_map::sequence hsplitter(master_keys_, vertical_split);
00682 hsplitter += 'X' - '@';
00683 hsplitter += '2';
00684 hsplitter.complete();
00685 key_bindings_doc.push_back("^X ^2 -- split viewer vertically");
00686
00687 master_key_map::sequence unsplitter(master_keys_, unsplit);
00688 unsplitter += 'X' - '@';
00689 unsplitter += '1';
00690 unsplitter.complete();
00691 key_bindings_doc.push_back("^X ^1 -- unify screen (hide all but one viewer)");
00692
00693 master_key_map::sequence nexter(master_keys_, next);
00694 nexter += 'X' - '@';
00695 nexter += 'o';
00696 nexter.complete();
00697 key_bindings_doc.push_back("^X o -- switch windows");
00698
00699 master_key_map::sequence nexter1(master_keys_, next);
00700 nexter1 += CursorWindow::key_f2;
00701 nexter1.complete();
00702 key_bindings_doc.push_back("F2 -- switch windows");
00703
00704 master_key_map::sequence helper(master_keys_, display_help);
00705 helper += CursorWindow::key_f1;
00706 helper.complete();
00707 key_bindings_doc.push_back("F1 -- get help");
00708
00709
00710
00711
00712
00713
00714
00715 master_key_map::sequence helper1(master_keys_, display_help);
00716 helper1 += 'X' - '@';
00717 helper1 += 'H' - '@';
00718 helper1.complete();
00719 key_bindings_doc.push_back("^X ^H -- get help");
00720
00721 master_key_map::sequence buffers(master_keys_, selector);
00722 buffers += 'X' - '@';
00723 buffers += 'B' - '@';
00724 buffers.complete();
00725 key_bindings_doc.push_back("^X ^B -- select viewer from list");
00726
00727 master_key_map::sequence killer(master_keys_, die);
00728 killer += 'X' - '@';
00729 killer += 'C' - '@';
00730 killer.complete();
00731 key_bindings_doc.push_back("^X ^C -- close all viewers and quit");
00732
00733 master_key_map::sequence kill_and_jumper(master_keys_, die_and_jump);
00734 kill_and_jumper += 'X' - '@';
00735 kill_and_jumper += 'J' - '@';
00736 kill_and_jumper.complete();
00737 key_bindings_doc.push_back("^X ^J -- same as ^C but leave curdir in ~/.tools_home/exitDir.txt");
00738
00739
00740 }
00741
00742 class appChooser
00743 : public Viewer
00744 {
00745 public:
00746
00759
00760 size_t display_top_;
00761 size_t cur_row_;
00762 int first_row_;
00763 bool active_;
00764
00765 appChooser(ViewerManager* vm)
00766 : Viewer(vm),
00767 display_top_(0),
00768 cur_row_(0),
00769 first_row_(2),
00770 active_(true)
00771 {
00772 }
00773
00774
00775 void operator() ( CursorWindow::viewport * vp,int cmd);
00777
00778 bool handle_event( CursorWindow::input_event const * e,
00779 CursorWindow::viewport * vp
00780 );
00781
00782 void repaint(CursorWindow::viewport *vp)
00783 {
00784 (*this)(vp, activate );
00785 }
00786
00787 void output_row_text(CursorWindow::viewport * vp, int i)
00788 {
00789
00790
00791 if( (size_t) i < manager_->apps_.size() )
00792 *vp << manager_->apps_[i].second
00793 ;
00794 }
00795
00796 static string app_name;
00797
00798 string const& application_name() const { return app_name; }
00799
00800 string description() const
00801 {
00802 return "lets you run a new application";
00803 }
00804 };
00805
00806 string appChooser::app_name("AppChooser");
00807
00808 void
00809 ViewerManager::
00810 handle_master_command(int cmd)
00811 {
00812
00813
00814
00815
00816 switch(cmd)
00817 {
00818
00819
00820
00821 case vertical_split : splitscreen_new_editor(false); return;
00822 case horizontal_split: splitscreen_new_editor(true); return;
00823
00824 case unsplit : unify(); return;
00825 case selector : vs(); return;
00826 case die : jump2dir=false; exit_dir_="" ; handle_die_request(); return;
00827 case die_and_jump : jump2dir=true; exit_dir_="" ; handle_die_request(); return;
00828 case new_application : add(new appChooser(this), "appchooser"); return;
00829 case new_viewer : popup_new_viewer(); return;
00830 case new_editor : popup_new_viewer(true); return;
00831
00832 case next : {
00833 if(viewports_.size() > 1)
00834 {
00835
00836
00837
00838
00839
00840
00841 if(active_viewport_)
00842 --active_viewport_;
00843 else
00844 active_viewport_ = viewports_.size() -1;
00845
00846 viewports_[active_viewport_]->activate();
00847
00848
00849
00850
00851
00852 repaint_handler *rh = viewports_[active_viewport_]->get_repaint_handler();
00853 Viewer *active = dynamic_cast<Viewer*>(rh);
00854
00855 for(size_t i = 0; i < viewers_.size(); ++i)
00856 {
00857 if(viewers_[i].first == active)
00858 {
00859 order_.activate(viewers_[i].second);
00860 break;
00861 }
00862 }
00863
00864
00865 }
00866 else
00867 if(viewers_.size() > 1)
00868 {
00869
00870
00871
00872
00873
00874
00875 Viewer* v = active_viewer();
00876
00877 size_t i;
00878
00879 for(i=0; i < viewers_.size(); ++i)
00880 {
00881 if(viewers_[i].first == v)
00882 {
00883 break;
00884 }
00885 }
00886
00887 if(i == 0)
00888 i = viewers_.size() -1;
00889 else
00890 --i;
00891
00892 activate(viewers_[i].first);
00893
00894
00895 order_.activate(viewers_[i].second);
00896
00897 }
00898 return;
00899 }
00900 case display_help : help(); return;
00901
00902 case interactive_shell:
00903 {
00904 row_col old_size;
00905 row_col new_size;
00906
00907 int err;
00908
00909 old_size = window()->size();
00910 window()->close();
00911
00912 string curdir = active_directory();
00913 char old_dir[2000];
00914
00915 if( 0 == getcwd(old_dir, sizeof(old_dir)) )
00916 old_dir[0] = 0;
00917
00918 err = chdir(curdir.c_str());
00919
00920 printf("Current directory is: ");
00921 fflush(stdout);
00922 err = system("pwd");
00923
00924 Viewer* av = active_viewer();
00925
00926
00927
00928 #ifndef _MSC_VER
00929
00930 printf("\nThe file or directory you are working on is:\n %s\n",
00931 av?av->description().c_str():""
00932 );
00933 printf("Starting your shell. Please use 'exit' to return\n");
00934 err = fflush(stdout);
00935 {
00936 char const *bash = getenv("BASH");
00937
00938 if(bash)
00939 err = system("bash -i");
00940 else
00941 err = system("/bin/sh -i");
00942
00943 }
00944 #else
00945
00946
00947 err = system("cmd /c cls");
00948 printf("\nThe file or directory you are working on is:\n %s\n",
00949 av?av->description().c_str():""
00950 );
00951 printf("Starting CMD.EXE. Please use 'exit' to return\n");
00952 err = fflush(stdout);
00953 err = system("cmd");
00954 #endif
00955
00956 err =chdir(old_dir);
00957
00958 window()->open();
00959 new_size = window()->size();
00960 window()->resize_viewports(old_size, new_size);
00961
00962 (void)(err);
00963 }
00964 return;
00965
00966 }
00967 }
00968
00969 void
00970 ViewerManager::
00971 run()
00972 {
00973
00974
00975
00976
00977 if(viewports_.size() == 0)
00978 {
00979 Viewer* chooser = new appChooser(this);
00980
00981 viewers_.push_back( vpentry(chooser, "appChooser") );
00982
00983 viewports_.push_back( cw_.new_viewport(chooser).release() );
00984
00985 viewports_.back()->activate();
00986 }
00987
00988 CursorWindow::input_event e;
00989
00990
00991
00992
00993
00994
00995
00996 for(;;)
00997 {
00998
00999
01000
01001
01002 e = cw_.read_input();
01003
01004 if(e.type_ != CursorWindow::input_event::DataKey &&
01005 e.type_ != CursorWindow::input_event::FunctionKey
01006 )
01007 {
01008 continue;
01009 }
01010
01011
01012
01013 master_key_map::search s(master_keys_);
01014
01015 int possible_cmd;
01016
01017 if(!s(e.value_))
01018 {
01019
01020
01021 dispatch_event(e);
01022
01023 }
01024 else
01025 if( (++s, s.finished(&possible_cmd) ) )
01026 {
01027
01028
01029 handle_master_command(possible_cmd);
01030 }
01031 else
01032 {
01033
01034
01035
01036
01037
01038 vector<input_event> l;
01039
01040 l.push_back(e);
01041
01042 for(;;)
01043 {
01044
01045
01046 e = cw_.read_input();
01047
01048 if(e.type_ != input_event::FunctionKey &&
01049 e.type_ != input_event::DataKey
01050 )
01051 {
01052
01053
01054
01055 size_t i = 0;
01056
01057 for(i=0; i < l.size(); ++i)
01058 dispatch_event(l[i]);
01059
01060 dispatch_event(e);
01061
01062 break;
01063 }
01064 else
01065 if(s(e.value_))
01066 {
01067
01068
01069 l.push_back(e);
01070
01071 ++s;
01072
01073 int id;
01074
01075 if(s.finished(&id))
01076 {
01077 handle_master_command(id);
01078 break;
01079 }
01080
01081 }
01082 else
01083 {
01084
01085
01086 size_t i = 0;
01087
01088 for(i=0; i < l.size(); ++i)
01089 dispatch_event(l[i]);
01090
01091 dispatch_event(e);
01092
01093 break;
01094 }
01095
01096 }
01097 }
01098 }
01099 }
01100
01101
01102
01103
01104 void
01105 ViewerManager::
01106 unify()
01107 {
01108
01109
01110
01111 Viewer *viewer = dynamic_cast<Viewer*>
01112 (viewports_[active_viewport_]->get_repaint_handler());
01113
01114 size_t i;
01115
01116 for(i = 0; i < viewports_.size(); ++i)
01117 {
01118 delete viewports_[i];
01119 }
01120
01121 viewports_.erase(viewports_.begin(), viewports_.end());
01122
01123 active_viewport_ = 0;
01124
01125 viewports_.push_back(cw_.new_viewport(viewer).release());
01126
01127 viewports_[active_viewport_]->activate();
01128
01129 }
01130
01131
01132 void
01133 ViewerManager::
01134 vs()
01135 {
01136
01137
01138
01139
01140
01141
01142
01143 size_t i;
01144
01145 for(i=0; i < viewports_.size(); ++i)
01146 {
01147 repaint_handler* rh = viewports_[i]->get_repaint_handler();
01148 Viewer* vp = dynamic_cast<Viewer*>(rh);
01149
01150 if(vp == vs_.get())
01151 {
01152 active_viewport_ = i;
01153 viewports_[i]->activate();
01154 return;
01155 }
01156 }
01157
01158
01159
01160
01161 if(viewports_.size())
01162 {
01163 viewports_[active_viewport_]->set_repaint_handler(vs_.get());
01164 viewports_[active_viewport_]->activate();
01165 return;
01166 }
01167
01168
01169
01170
01171 return;
01172
01173 }
01174
01175
01176 void
01177 ViewerSelector::
01178 operator() ( CursorWindow::viewport * vp,int cmd)
01179 {
01180
01181
01182
01183
01184 size_t viewers = manager_->viewers_.size();
01185 row_col vpsize = vp->size();
01186 row_col vporigin= vp->origin();
01187
01188 if(cmd == CursorWindow::viewport::repaint_handler::activate)
01189 active_=true;
01190 else
01191 if(cmd == CursorWindow::viewport::repaint_handler::deactivate)
01192 active_=false;
01193
01194 int left = 0;
01195
01196 if(vporigin.col_) ++left;
01197
01198
01199
01200
01201 vp->set_text_attribute(ViewerManager::normal_att);
01202
01203 vp->set_curpos(0,0);
01204 vp->fill_to_eos();
01205
01206 if(left)
01207 {
01208 for(int i = 0; i < vpsize.row_; ++i)
01209 {
01210 vp->set_curpos(i, 0);
01211
01212
01213
01214 using namespace CursesInterface;
01215
01216 vp->write(line_chars[VL_MIDDLE]);
01217 }
01218 }
01219
01220 vp->set_curpos(vpsize.row_-1, left);
01221 vp->set_text_attribute(ViewerManager::bottom_att);
01222 vp->fill_to_eol();
01223
01224
01225
01226
01227 vp->set_curpos(0,left);
01228 if(active_)
01229 vp->set_text_attribute(ViewerManager::active_title_att);
01230 else
01231 vp->set_text_attribute(ViewerManager::inactive_title_att);
01232
01233 *vp << "Select one of " << viewers << " viewers";
01234 vp->fill_to_eol();
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 int row = first_row_;
01246
01247 for(size_t i = display_top_;
01248 row < vpsize.row_ && i < viewers;
01249 ++i, ++row
01250 )
01251 {
01252
01253 vp->set_text_attribute(ViewerManager::normal_att);
01254
01255 if(row == vpsize.row_-1 && i != cur_row_)
01256 {
01257 vp->set_text_attribute(ViewerManager::bottom_att);
01258 }
01259 else
01260 if(i == cur_row_)
01261 {
01262
01263
01264 vp->set_curpos(row, left);
01265 vp->set_text_attribute(active_ ? ViewerManager::highlighted_att
01266 : ViewerManager::inactive_mark_att
01267 );
01268 vp->fill_to_eol();
01269
01270
01271 }
01272
01273 vp->set_curpos(row, 2+left);
01274
01275 output_row_text(vp, i);
01276
01277 }
01278
01279 vp->set_text_attribute(ViewerManager::normal_att);
01280
01281 vp->set_curpos(first_row_ + cur_row_ - display_top_,left);
01282
01283
01284 }
01285
01286 bool
01287 ViewerSelector::
01288 handle_event( CursorWindow::input_event const * e,
01289 CursorWindow::viewport * vp
01290 )
01291 {
01292
01293
01294
01295
01296
01297 if(e->type_ == CursorWindow::input_event::ForceExitKey)
01298 return true;
01299
01300
01301 if(e->type_ != CursorWindow::input_event::DataKey &&
01302 e->type_ != CursorWindow::input_event::FunctionKey
01303 )
01304 return false;
01305
01306
01307
01308
01309 int row = first_row_ + (cur_row_ - display_top_);
01310 row_col size = vp->size();
01311 row_col vporigin = vp->origin();
01312
01313 int bottom_row = size.row_ - first_row_ - 1;
01314
01315 int left = 0;
01316
01317 if(vporigin.col_) ++left;
01318
01319 vp->set_curpos(row,left);
01320 vp->set_text_attribute(row == bottom_row ? ViewerManager::bottom_att
01321 : ViewerManager::normal_att);
01322
01323 *vp << " ";
01324
01325 output_row_text(vp, cur_row_);
01326
01327 vp->fill_to_eol();
01328
01329 int edit_func = vp->window()->func[e->value_];
01330
01331 switch(edit_func)
01332 {
01333 case CursorWindow::func_top:
01334 row = first_row_;
01335 cur_row_ = 0;
01336 display_top_ = 0;
01337 vp->activate();
01338 break;
01339
01340 case CursorWindow::func_bottom:
01341 row = first_row_;
01342 cur_row_ = manager_->viewers_.size()-1;
01343
01344 if( (int) cur_row_ < 0)
01345 cur_row_ = 0;
01346
01347 display_top_ = cur_row_;
01348 vp->activate();
01349 break;
01350
01351 case CursorWindow::func_up:
01352
01353
01354
01355 if(row == first_row_)
01356 {
01357 if(cur_row_ > 0)
01358 {
01359
01360
01361 int page_length = size.row_ - first_row_;
01362
01363 display_top_ -= page_length;
01364
01365 if( (int) display_top_ < 0)
01366 display_top_ = 0;
01367
01368 cur_row_ = display_top_ + page_length-1;
01369
01370 if(cur_row_ >= manager_->viewers_.size())
01371 {
01372 cur_row_ = manager_->viewers_.size() -1;
01373 }
01374
01375 if( (int)(cur_row_) < 0 )
01376 cur_row_ = 0;
01377
01378 row = first_row_ + (cur_row_ - display_top_);
01379
01380 repaint(vp);
01381 }
01382 }
01383 else
01384 {
01385 --row;
01386 --cur_row_;
01387 }
01388
01389 break;
01390 case CursorWindow::func_down:
01391
01392
01393
01394 if(row == size.row_ - 1)
01395 {
01396
01397
01398
01399 row = first_row_;
01400
01401 display_top_ += size.row_ - first_row_;
01402
01403 if( (int)(display_top_) >= (int)(manager_->viewers_.size()))
01404 {
01405 display_top_ -= size.row_ - first_row_ -1;
01406
01407 if( ((int)display_top_) < 0 )
01408 display_top_ = 0;
01409 }
01410
01411 cur_row_ = display_top_;
01412
01413 repaint(vp);
01414
01415 }
01416 else
01417 {
01418
01419
01420 if(cur_row_ < manager_->viewers_.size()-1)
01421 {
01422 ++row;
01423 ++cur_row_;
01424 }
01425 }
01426 break;
01427 case CursorWindow::func_prior:
01428
01429
01430
01431 display_top_ -= size.row_ - first_row_;
01432
01433 if( (int)(display_top_) < 0)
01434 display_top_ = 0;
01435
01436 cur_row_ = display_top_;
01437
01438 row = first_row_;
01439
01440 repaint(vp);
01441
01442 break;
01443
01444 case CursorWindow::func_next:
01445
01446
01447
01448 display_top_ += size.row_ - first_row_;
01449
01450 if( (int)(display_top_) >= (int)manager_->viewers_.size() )
01451 display_top_ = manager_->viewers_.size()-1;
01452
01453 if( (int)(display_top_) < 0 )
01454 display_top_ = 0;
01455
01456 cur_row_ = display_top_;
01457
01458 row = first_row_;
01459
01460 repaint(vp);
01461
01462 break;
01463
01464 case CursorWindow::func_clreol:
01465 goto undisplay_viewer_selector;
01466
01467 case CursorWindow::func_enter:
01468
01469
01470
01471
01472
01473 {
01474 Viewer* selectee = manager_->viewers_[cur_row_].first;
01475
01476 manager_->order_.activate( manager_->viewers_[cur_row_].second );
01477
01478 vector<viewport*> &viewports_ = manager_->viewports_;
01479
01480 size_t i;
01481
01482 bool found=false;
01483
01484 for(i = 0; i < viewports_.size(); ++i)
01485 {
01486 repaint_handler *rh = viewports_[i]->get_repaint_handler();
01487
01488 Viewer* vp = dynamic_cast<Viewer*>(rh);
01489
01490 if(vp == selectee)
01491 {
01492
01493 viewports_[i]->activate();
01494 manager_->active_viewport_ = i;
01495 found = true;
01496 return false;
01497 }
01498 }
01499
01500 if(!found)
01501 {
01502
01503
01504
01505 viewports_[manager_->active_viewport_]->set_repaint_handler(selectee);
01506 viewports_[manager_->active_viewport_]->activate();
01507
01508 return false;
01509
01510 }
01511
01512 }
01513 break;
01514
01515 case CursorWindow::func_data:
01516 switch(e->value_)
01517 {
01518 case 'q':
01519 {
01520 undisplay_viewer_selector:
01521
01522
01523 size_t &active_viewport_ = manager_->active_viewport_;
01524
01525 vector<CursorWindow::viewport*> &viewports_ = manager_->viewports_;
01526
01527 delete viewports_[active_viewport_];
01528
01529 viewports_.erase(viewports_.begin() + active_viewport_);
01530
01531 if(active_viewport_ >= viewports_.size())
01532 active_viewport_ = viewports_.size() -1 ;
01533
01534 if( ((int)active_viewport_) < 0 )
01535 active_viewport_ = 0;
01536
01537 if( viewports_.size() )
01538 {
01539 viewports_[active_viewport_]->activate();
01540 }
01541 else
01542 {
01543 vector<ViewerManager::vpentry> &viewers_ =
01544 manager_->viewers_;
01545
01546 if( viewers_.size() == 0 ||
01547 (
01548 viewers_.size() == 1 &&
01549 viewers_[0].first == this
01550 )
01551 )
01552 manager_->exit();
01553 else
01554 viewports_.push_back(manager_->
01555 cw_.new_viewport(viewers_[0].first).release());
01556
01557 viewports_[0]->activate();
01558
01559 }
01560
01561 return false;
01562 }
01563 break;
01564 }
01565 break;
01566
01567
01568 }
01569
01570
01571
01572 vp->set_curpos(row,left);
01573 vp->set_text_attribute(ViewerManager::highlighted_att);
01574
01575 *vp << " ";
01576
01577 output_row_text(vp, cur_row_);
01578
01579 vp->fill_to_eol();
01580
01581 vp->set_curpos(row,left);
01582 vp->set_text_attribute(row == bottom_row ? ViewerManager::bottom_att
01583 : ViewerManager::normal_att);
01584
01585 return false;
01586 }
01587
01589
01590
01591 void
01592 appChooser::
01593 operator() ( CursorWindow::viewport * vp,int cmd)
01594 {
01595
01596
01597
01598
01599 if(cmd == CursorWindow::viewport::repaint_handler::activate)
01600 active_ = true;
01601 else
01602 if(cmd == CursorWindow::viewport::repaint_handler::deactivate)
01603 active_ = false;
01604
01605 size_t apps = manager_->apps_.size();
01606 row_col vpsize = vp->size();
01607 row_col vporigin= vp->origin();
01608
01609 int left = 0;
01610
01611 if(vporigin.col_) ++left;
01612
01613
01614 vp->set_text_attribute(ViewerManager::normal_att);
01615 vp->set_curpos(0,0);
01616 vp->fill_to_eos();
01617
01618 if(left)
01619 {
01620 for(int i = 0; i < vpsize.row_; ++i)
01621 {
01622 vp->set_curpos(i, 0);
01623
01624 using namespace CursesInterface;
01625
01626 vp->write(line_chars[VL_MIDDLE]);
01627 }
01628 }
01629
01630
01631 vp->set_curpos(vpsize.row_-1, left);
01632 vp->set_text_attribute(ViewerManager::bottom_att);
01633 vp->fill_to_eol();
01634
01635
01636
01637
01638 vp->set_curpos(0,left);
01639
01640 if(active_)
01641 vp->set_text_attribute(ViewerManager::active_title_att);
01642 else
01643 vp->set_text_attribute(ViewerManager::inactive_title_att);
01644
01645 *vp << "Select one of " << apps << " applications";
01646 vp->fill_to_eol();
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657 int row = first_row_;
01658
01659 for(size_t i = display_top_;
01660 row < vpsize.row_ && i < apps;
01661 ++i, ++row
01662 )
01663 {
01664
01665 vp->set_text_attribute(ViewerManager::normal_att);
01666
01667 if(row == vpsize.row_-1 && i != cur_row_)
01668 {
01669 vp->set_text_attribute(ViewerManager::bottom_att);
01670 }
01671 else
01672 if(i == cur_row_)
01673 {
01674
01675
01676 vp->set_curpos(row, left);
01677 vp->set_text_attribute(ViewerManager::highlighted_att);
01678 vp->fill_to_eol();
01679
01680
01681 }
01682
01683 vp->set_curpos(row, 2+left);
01684
01685 output_row_text(vp, i);
01686
01687 }
01688
01689 vp->set_text_attribute(ViewerManager::normal_att);
01690
01691 vp->set_curpos(first_row_ + cur_row_ - display_top_,left);
01692
01693
01694 }
01695
01696 bool
01697 appChooser::
01698 handle_event( CursorWindow::input_event const * e,
01699 CursorWindow::viewport * vp
01700 )
01701 {
01702
01703
01704
01705
01706
01707 if(e->type_ == CursorWindow::input_event::ForceExitKey)
01708 return true;
01709
01710 if(e->type_ != CursorWindow::input_event::DataKey &&
01711 e->type_ != CursorWindow::input_event::FunctionKey
01712 )
01713 return false;
01714
01715 if(manager_->apps_.size() == 0)
01716 return true;
01717
01718
01719
01720
01721 int row = first_row_ + (cur_row_ - display_top_);
01722 row_col size = vp->size();
01723 row_col vporigin= vp->origin();
01724
01725 int left = 0;
01726
01727 if(vporigin.col_) ++left;
01728
01729 vp->set_curpos(row,left);
01730 vp->set_text_attribute(ViewerManager::normal_att);
01731
01732 *vp << " ";
01733
01734 output_row_text(vp, cur_row_);
01735
01736 vp->fill_to_eol();
01737
01738 int edit_func = vp->window()->func[e->value_];
01739
01740 switch(edit_func)
01741 {
01742 case CursorWindow::func_top:
01743 row = first_row_;
01744 cur_row_ = 0;
01745 display_top_ = 0;
01746 vp->activate();
01747 break;
01748
01749 case CursorWindow::func_bottom:
01750 row = first_row_;
01751 cur_row_ = manager_->viewers_.size()-1;
01752
01753 if( (int) cur_row_ < 0)
01754 cur_row_ = 0;
01755
01756 display_top_ = cur_row_;
01757 vp->activate();
01758 break;
01759 case CursorWindow::func_up:
01760
01761
01762
01763 if(row == first_row_)
01764 {
01765 if(cur_row_ > 0)
01766 {
01767
01768
01769 int page_length = size.row_ - first_row_;
01770
01771 display_top_ -= page_length;
01772
01773 if( (int) display_top_ < 0)
01774 display_top_ = 0;
01775
01776 cur_row_ = display_top_ + page_length-1;
01777
01778 if(cur_row_ >= manager_->apps_.size())
01779 {
01780 cur_row_ = manager_->apps_.size() -1;
01781 }
01782
01783 if( (int)(cur_row_) < 0 )
01784 cur_row_ = 0;
01785
01786 row = first_row_ + (cur_row_ - display_top_);
01787
01788 repaint(vp);
01789
01790 }
01791 }
01792 else
01793 {
01794 --row;
01795 --cur_row_;
01796 }
01797
01798 break;
01799 case CursorWindow::func_down:
01800
01801
01802
01803 if(row == size.row_ - 1)
01804 {
01805
01806
01807
01808 row = first_row_;
01809
01810 display_top_ += size.row_ - first_row_;
01811
01812 if( (int)(display_top_) >= (int)(manager_->apps_.size()))
01813 {
01814 display_top_ -= size.row_ - first_row_ -1;
01815
01816 if( ((int)display_top_) < 0 )
01817 display_top_ = 0;
01818 }
01819
01820 cur_row_ = display_top_;
01821
01822 repaint(vp);
01823
01824 }
01825 else
01826 {
01827
01828
01829 if(cur_row_ < manager_->apps_.size()-1)
01830 {
01831 ++row;
01832 ++cur_row_;
01833 }
01834 }
01835 break;
01836 case CursorWindow::func_prior:
01837
01838
01839
01840 display_top_ -= size.row_ - first_row_;
01841
01842 if( (int)(display_top_) < 0)
01843 display_top_ = 0;
01844
01845 cur_row_ = display_top_;
01846
01847 row = first_row_;
01848
01849 repaint(vp);
01850
01851 break;
01852
01853 case CursorWindow::func_next:
01854
01855
01856
01857 display_top_ += size.row_ - first_row_;
01858
01859 if( (int)(display_top_) >= (int)manager_->apps_.size() )
01860 display_top_ = manager_->apps_.size()-1;
01861
01862 if( (int)(display_top_) < 0 )
01863 display_top_ = 0;
01864
01865 cur_row_ = display_top_;
01866
01867 row = first_row_;
01868
01869 repaint(vp);
01870
01871 break;
01872
01873
01874 case CursorWindow::func_enter:
01875 {
01876
01877
01878
01879
01880
01881 ViewerManager::application app = manager_->apps_[cur_row_].first;
01882
01883 string fullname;
01884
01885 Viewer* rv = (*app)(manager_, fullname);
01886
01887 if(rv)
01888 {
01889
01890
01891
01892
01893 {
01894
01895
01896
01897
01898 for(size_t i=0; i < manager_->viewers_.size(); ++i)
01899 {
01900 if(manager_->viewers_[i].first == rv)
01901 {
01902 manager_->activate(rv);
01903
01904 {
01905 for(i = 0; i < manager_->viewports_.size(); ++i)
01906 {
01907 if(manager_->viewports_[i]->get_repaint_handler() == rv)
01908 {
01909 manager_->override_active_viewport_ = i;
01910 break;
01911 }
01912 }
01913 }
01914
01915 return true;
01916 }
01917 }
01918
01919 }
01920
01921
01922 size_t i;
01923
01924 typedef ViewerManager::vpentry vpentry;
01925
01926 vector<viewport*> &viewports_ = manager_->viewports_;
01927 vector<vpentry> &viewers_ = manager_->viewers_;
01928
01929 viewports_[manager_->active_viewport_]->set_repaint_handler(rv);
01930
01931
01932 for(i=0; i < viewers_.size(); ++i)
01933 {
01934 if(viewers_[i].first == this)
01935 {
01936 viewers_[i].first = rv;
01937 viewers_[i].second = fullname;
01938
01939 viewports_[manager_->active_viewport_]->activate();
01940
01941 return false;
01942 }
01943 }
01944 }
01945
01946 return true;
01947
01948 }
01949 break;
01950
01951 case CursorWindow::func_data:
01952 switch(e->value_)
01953 {
01954 case 'q':
01955 return true;
01956 }
01957 break;
01958
01959
01960 }
01961
01962
01963
01964 vp->set_curpos(row,left);
01965 vp->set_text_attribute(ViewerManager::highlighted_att);
01966
01967 *vp << " ";
01968
01969 output_row_text(vp, cur_row_);
01970
01971 vp->fill_to_eol();
01972
01973 vp->set_curpos(row,left);
01974 vp->set_text_attribute(ViewerManager::normal_att);
01975
01976 return false;
01977 }
01978
01979 Viewer*
01980 ViewerManager::
01981 find_viewer(string const &viewername)
01982 {
01983 for(size_t i=0; i < viewers_.size(); ++i)
01984 {
01985 if( viewers_[i].second == viewername)
01986 return viewers_[i].first;
01987 }
01988
01989 return 0;
01990 }
01991
01992
01993
01994 std::string
01995 ViewerManager::
01996 find_viewer_name(Viewer *vp)
01997 {
01998 for(size_t i=0; i < viewers_.size(); ++i)
01999 {
02000 if( viewers_[i].first == vp)
02001 return viewers_[i].second;
02002 }
02003
02004 return std::string();
02005 }
02006
02007
02008 void
02009 ViewerManager::
02010 help()
02011 {
02012 Viewer* active = active_viewer();
02013
02014 active->help();
02015
02016 }
02017
02018
02019
02020 void
02021 ViewerManager::
02022 help_helper( list<string>& help_info )
02023 {
02024 CursorWindow::Message m("Help");
02025
02026
02027
02028
02029
02030 {
02031 list< string >::iterator first = help_info.begin(),
02032 last = help_info.end();
02033
02034 while(first != last)
02035 {
02036 string &t = *first++;
02037
02038 m += t;
02039
02040 }
02041 }
02042
02043
02044
02045
02046
02047 m += "";
02048 m += string("Executable: ") + executable_name_ + ":" ;
02049 m += " " + executable_version_;
02050 m += "";
02051 m += "System command bindings are as follows:";
02052 m += "";
02053
02054 {
02055 list<string>::iterator first = key_bindings_doc.begin(),
02056 last = key_bindings_doc.end();
02057
02058 while(first != last)
02059 {
02060 string &s = *first++;
02061
02062 m += " " + s;
02063
02064 }
02065 }
02066
02067 m += "";
02068 m += "Standard edit function key bindings";
02069 m += " (some may not apply):";
02070 m += "";
02071
02072 {
02073 CursorWindow* window = this->window();
02074
02075 map<int,int>::iterator first = window->func.begin(),
02076 last = window->func.end();
02077 while(first != last)
02078 {
02079 map<int,int>::value_type& cur = *first++;
02080
02081 int key = cur.first;
02082 int func= cur.second;
02083
02084 if(func != CursorWindow::func_data)
02085 {
02086
02087 string key_name = CursorWindow::key_name(key);
02088 string func_name = CursorWindow::func_name(func);
02089
02090 while(key_name.size() < 8)
02091 key_name += ' ';
02092
02093 m += string(" ") + key_name + string(" -- ") + func_name;
02094 }
02095
02096 }
02097
02098
02099 }
02100
02101
02102
02103 m.popup(window());
02104
02105 }
02106
02107
02108 Viewer*
02109 ViewerManager::
02110 open(string const &_fullname)
02111 {
02112 FileName fullname(_fullname);
02113
02114 if(fullname.is_dir())
02115 {
02116 if(!dir_opener_)
02117 return 0;
02118
02119 return (*dir_opener_)(this, fullname);
02120
02121 }
02122 else
02123 {
02124
02125
02126 string basepart = fullname.basename();
02127
02128 string::iterator first = basepart.begin(),
02129 last = basepart.end();
02130
02131 while(first != last)
02132 {
02133 char c = *first++;
02134
02135 if(c == '*' || c == '?')
02136 {
02137 if(!dir_opener_)
02138 return 0;
02139
02140 return (*dir_opener_)(this, fullname);
02141 }
02142 }
02143
02144 }
02145
02146
02147
02148
02149 string ext = fullname.extension();
02150
02151 if(ext.size())
02152 {
02153 list<opener_map_entry>::iterator first = openers_.begin(),
02154 last = openers_.end();
02155
02156 while(first != last)
02157 {
02158 opener_map_entry & cur = *first++;
02159
02160 std::string const &supported = cur.second;
02161
02162
02163 if(supported == ext)
02164 return (*cur.first)(this, fullname);
02165 }
02166
02167
02168
02169 }
02170
02171 if(openers_.begin() != openers_.end())
02172 {
02173 application app= openers_.back().first;
02174
02175 return (*app)(this, fullname);
02176
02177 }
02178
02179
02180 return 0;
02181
02182
02183 }
02184
02185 void
02186 ViewerManager::
02187 set_directory_app(application a)
02188 {
02189 dir_opener_ = a;
02190 }
02191
02192 void
02193 ViewerManager::
02194 add_viewer_app(application a, string filename_extension)
02195 {
02196 openers_.push_front( opener_map_entry(a,filename_extension) );
02197 }
02198
02199 void
02200 ViewerManager::
02201 add_editor_app(application a, string filename_extension)
02202 {
02203 editors_.push_front( opener_map_entry(a,filename_extension) );
02204 }
02205
02206 Viewer*
02207 ViewerManager::
02208 edit(string const &_fullname)
02209 {
02210 FileName fullname(_fullname);
02211
02212 if(fullname.is_dir())
02213 {
02214 if(!dir_opener_)
02215 return 0;
02216
02217 string name = fullname + "/*";
02218
02219 return (*dir_opener_)(this, name);
02220
02221 }
02222 else
02223 {
02224
02225
02226 string basepart = fullname.basename();
02227
02228 string::iterator first = basepart.begin(),
02229 last = basepart.end();
02230
02231 while(first != last)
02232 {
02233 char c = *first++;
02234
02235 if(c == '*' || c == '?')
02236 {
02237 if(!dir_opener_)
02238 return 0;
02239
02240 return (*dir_opener_)(this, fullname);
02241 }
02242 }
02243
02244 }
02245
02246
02247
02248
02249 string ext = fullname.extension();
02250
02251 if(ext.size())
02252 {
02253 list<opener_map_entry>::iterator first = editors_.begin(),
02254 last = editors_.end();
02255
02256 while(first != last)
02257 {
02258 opener_map_entry & cur = *first++;
02259
02260 std::string const &supported = cur.second;
02261
02262 if(supported == ext)
02263 return (*cur.first)(this, fullname);
02264 }
02265
02266
02267
02268 }
02269
02270 if(editors_.begin() != editors_.end())
02271 {
02272
02273
02274
02275 application app= 0;
02276
02277 list<opener_map_entry>::iterator first = editors_.begin(),
02278 last = editors_.end();
02279
02280 while(first != last)
02281 {
02282 opener_map_entry & cur = *first++;
02283
02284 if(cur.second == "")
02285 {
02286 app = cur.first;
02287 break;
02288 }
02289 }
02290
02291 if(app == 0)
02292 app= editors_.back().first;
02293
02294 return (*app)(this, fullname);
02295
02296 }
02297
02298
02299 return 0;
02300
02301
02302 }
02303
02304 string
02305 ViewerManager::
02306 active_directory() const
02307 {
02308 ViewerManager* me = const_cast<ViewerManager*>(this);
02309
02310 Viewer* av = me->active_viewer();
02311
02312 FileName pattern;
02313
02314 if(!av)
02315 pattern="/";
02316 else
02317 {
02318 vector<vpentry>::iterator first = me->viewers_.begin(),
02319 last = me->viewers_.end();
02320
02321 while(first != last)
02322 {
02323 vpentry& e = *first;
02324
02325 if(e.first == av)
02326 {
02327 pattern=e.second;
02328 pattern = pattern.dirname();
02329
02330 break;
02331 }
02332
02333 ++first;
02334
02335 }
02336
02337 if(first == last)
02338 {
02339 pattern="/";
02340 }
02341
02342 }
02343
02344 return pattern;
02345
02346 }
02347
02348
02349 void
02350 ViewerManager::
02351 popup_new_viewer(bool use_edit)
02352 {
02353 FileName pattern = active_directory();
02354
02355
02356
02357
02358 CursorWindow::Dialog d( use_edit ? "Edit file or directory"
02359 : "View file or directory"
02360 );
02361
02362 d.set_completion_directory(pattern);
02363
02364 d += new CursorWindow::Dialog::String("name",
02365 "Pathname",
02366 "",
02367 40
02368 );
02369
02370 if(d.popup(window()))
02371 return ;
02372
02373 string file = d.element_value("name");
02374
02375
02376 if(file.size())
02377 {
02378 FileName f(file);
02379
02380 f = f.expand_tildes();
02381
02382 if(!f.is_absolute_path())
02383 f = pattern + f;
02384
02385 f.convert_to_absolute_path();
02386
02387 if(f.is_dir())
02388 {
02389 char lastChar = f[f.size()-1];
02390
02391 if(lastChar != '/' && lastChar != '\\')
02392 f += '/';
02393
02394 f += '*';
02395 }
02396
02397 Viewer* extant_viewer = find_viewer(f);
02398
02399 if(extant_viewer)
02400 {
02401 activate(extant_viewer);
02402
02403 if(override_active_viewport_ < viewports_.size())
02404 {
02405 active_viewport_ = override_active_viewport_;
02406 override_active_viewport_ = 10000;
02407 }
02408
02409 return;
02410 }
02411
02412 Viewer* newbie;
02413
02414 if(use_edit)
02415 newbie = edit(f);
02416 else
02417 newbie = open(f);
02418
02419 if(newbie)
02420 add(newbie, f);
02421
02422 }
02423
02424 }
02425
02426 bool
02427 ViewerManager::
02428 is_visible(Viewer* v)
02429 {
02430
02431 vector<viewport*>::iterator vp_next = viewports_.begin(),
02432 vp_last = viewports_.end();
02433
02434 while(vp_next != vp_last)
02435 {
02436 viewport* entry = *vp_next++;
02437
02438 repaint_handler *rh = entry->get_repaint_handler();
02439
02440 Viewer* vp = dynamic_cast<Viewer*>(rh);
02441
02442 if(vp == v)
02443 {
02444
02445
02446
02447 return true;
02448
02449 }
02450
02451 }
02452
02453 return false;
02454 }
02455
02456
02457 void
02458 ViewerManager::
02459 splitscreen_new_editor(bool horizontal)
02460 {
02461 FileName pattern = active_directory();
02462
02463 string title;
02464
02465 if(horizontal)
02466 title = "Horizontally ";
02467 else
02468 title = "Vertically ";
02469
02470 title += "Split window and edit (leave name blank for buffer list)";
02471
02472 CursorWindow::Dialog d(title);
02473
02474 d.set_completion_directory(pattern);
02475
02476 d += new CursorWindow::Dialog::String("name",
02477 "Pathname",
02478 "",
02479 40
02480 );
02481
02482 if(d.popup(window()))
02483 return ;
02484
02485 string file = d.element_value("name");
02486
02487
02488
02489 while( file.size() && file[0] == ' ')
02490 file.erase( file.begin() );
02491
02492
02493
02494
02495 if(file.size() == 0)
02496 {
02497
02498
02499
02500
02501 size_t i;
02502
02503 for(i=0; i < viewports_.size(); ++i)
02504 {
02505 repaint_handler* rh = viewports_[i]->get_repaint_handler();
02506 Viewer* vp = dynamic_cast<Viewer*>(rh);
02507
02508 if(vp == vs_.get())
02509 {
02510 active_viewport_ = i;
02511 viewports_[i]->activate();
02512 return;
02513 }
02514 }
02515
02516
02517
02518
02519
02520 if(horizontal)
02521 hsplit(vs_.get(), "Viewer Selector");
02522 else
02523 vsplit(vs_.get(), "Viewer Selector");
02524
02525
02526 }
02527 else
02528 {
02529 FileName f(file);
02530
02531 if(!f.is_absolute_path())
02532 f = pattern + f;
02533
02534 f.convert_to_absolute_path();
02535
02536 if(f.is_dir())
02537 f += "/*";
02538
02539 Viewer* extant_viewer = find_viewer(f);
02540
02541 if(extant_viewer)
02542 {
02543 if(is_visible(extant_viewer))
02544 {
02545 activate(extant_viewer);
02546
02547 if(override_active_viewport_ < viewports_.size())
02548 {
02549 active_viewport_ = override_active_viewport_;
02550 override_active_viewport_ = 10000;
02551 }
02552 }
02553 else
02554 {
02555 if(horizontal)
02556 hsplit(extant_viewer, f);
02557 else
02558 vsplit(extant_viewer, f);
02559 }
02560 return;
02561 }
02562
02563 Viewer* newbie;
02564
02565 newbie = edit(f);
02566
02567 if(newbie)
02568 {
02569 if(horizontal)
02570 hsplit(newbie, f);
02571 else
02572 vsplit(newbie, f);
02573 }
02574
02575 }
02576
02577 }
02578
02579 void
02580 ViewerManager::
02581 handle_die_request()
02582 {
02583
02584
02585 string curdir=active_directory();
02586
02587 if(exit_dir_.size() == 0)
02588 {
02589 exit_dir_ = curdir;
02590 }
02591
02592 bool clean_viewer_found=true;
02593
02594 while(clean_viewer_found)
02595 {
02596 size_t viewers = viewers_.size();
02597
02598 clean_viewer_found = false;
02599
02600 for(size_t i=0; i < viewers; ++i)
02601 {
02602 if(!viewers_[i].first->is_dirty())
02603 {
02604 CursorWindow::input_event e;
02605
02606 e.type_ = CursorWindow::input_event::ForceExitKey;
02607
02608 activate(viewers_[i].first);
02609
02610 dispatch_event(e);
02611
02612
02613 clean_viewer_found = true;
02614
02615 break;
02616
02617 }
02618 }
02619
02620 }
02621
02622 if(viewers_.size() == 0)
02623 {
02624 recordExitDir();
02625
02626 exit();
02627
02628 }
02629
02630 unify();
02631
02632 {
02633 active_viewport()->beep();
02634
02635 CursorWindow::Message m("Unsaved edit changes exist");
02636
02637 m += " You must manually close all edit sessions";
02638 m += " with unsaved changes";
02639
02640 m.popup(window());
02641 }
02642
02643
02644
02645 }
02646
02647 string
02648 ViewerManager::
02649 default_etags_path(string &default_etags_path, char const *tagfileName)
02650 {
02651
02652
02653
02654
02655 string etagspath = ProgramOptions::global_options_->getenv("ETAGSPATH");
02656 string home = ProgramOptions::global_options_->getenv("HOME");
02657 string cdpath = ProgramOptions::global_options_->getenv("CDPATH");
02658
02659 if(cdpath.size())
02660 {
02661 default_etags_path += cdpath;
02662 default_etags_path += FileName::PATH_separator;
02663 }
02664
02665 default_etags_path += ".";
02666 default_etags_path += FileName::PATH_separator;
02667 default_etags_path += "..";
02668 default_etags_path += FileName::PATH_separator;
02669 default_etags_path += home;
02670
02671 if(etagspath.size())
02672 {
02673 default_etags_path = etagspath;
02674 }
02675
02676 FileName tagsfile = FileName::find_file_in_path(tagfileName, default_etags_path);
02677
02678 return tagsfile;
02679
02680 }
02681
02682 EtagsDB*
02683 ViewerManager::default_etags_db()
02686 {
02687 static EtagsDB* rv = 0;
02688
02689 if(rv == 0)
02690 {
02691 rv = new EtagsDB;
02692
02693 string tagsfile;
02694
02695 string default_etags_path;
02696
02697 tagsfile = ViewerManager::default_etags_path(default_etags_path);
02698
02699 rv->set_tags_file(tagsfile);
02700
02701 if(!rv->ok())
02702 {
02703 string sp(" ");
02704
02705 CursorWindow::Message m("Error opening 'TAGS' file");
02706
02707 m += "Couldn't find the TAGS file in any directory defined by $ETAGSPATH:";
02708
02709 StrTool::stringlist_t l;
02710
02711 string default_etags_path;
02712
02713 ViewerManager::default_etags_path(default_etags_path);
02714
02715 StrTool::parse_words(default_etags_path, &l, 10000, FileName::is_separator());
02716
02717 StrTool::stringlist_t::iterator first = l.begin(),
02718 last = l.end();
02719
02720 while(first != last)
02721 {
02722 m += *first++;
02723 }
02724
02725 active_viewport()->beep();
02726
02727 m.popup(active_viewport()->window());
02728
02729 return 0;
02730 }
02731
02732
02733 }
02734
02735 return rv;
02736 }
02737
02738 CppTagDB::Info*
02739 ViewerManager::default_cpptags_db()
02742 {
02743 static CppTagDB::Info* rv = 0;
02744
02745 if(rv == 0)
02746 {
02747 rv = new CppTagDB::Info;
02748
02749 string path;
02750
02751 string tagppFile = default_etags_path(path,"TAGPP.tagpp");
02752
02753 int failedLine=-1;
02754
02755 int err = rv->populate(tagppFile, failedLine);
02756
02757 if(err)
02758 {
02759 string sp(" ");
02760
02761 CursorWindow::Message m("Error opening TAGPP.tagpp file");
02762
02763 m += "Couldn't find the TAGPP.tagpp file in any directory defined by $ETAGSPATH:";
02764
02765 StrTool::stringlist_t l;
02766
02767 string default_etags_path;
02768
02769 StrTool::parse_words(path, &l, 10000, FileName::is_separator());
02770
02771 StrTool::stringlist_t::iterator first = l.begin(),
02772 last = l.end();
02773
02774 while(first != last)
02775 {
02776 m += *first++;
02777 }
02778
02779 active_viewport()->beep();
02780
02781 m.popup(active_viewport()->window());
02782
02783 return 0;
02784 }
02785
02786
02787 }
02788
02789 return rv;
02790 }
02791
02792
02793 struct is_pathsep
02794 {
02795 bool operator() (char c) const { return c == '/' || c == '\\'; }
02796 };
02797
02798
02799 int
02800 ViewerManager::
02801 find_files(string operand,
02802 list<string> *results
02803 )
02804 {
02805 FileName tmp(operand);
02806
02807 if(tmp.is_absolute_path())
02808 {
02809 results->push_back(tmp);
02810 return 1;
02811 }
02812
02813 int count = 0;
02814
02815
02816 {
02817 StrTool::stringlist_t dirs;
02818 int count = StrTool::parse_words(ProgramOptions::global_options_->getenv("CDPATH"),
02819 &dirs,
02820 1000000,
02821 StrTool::Is_Colon()
02822 );
02823
02824 StrTool::stringlist_t::iterator f, l;
02825
02826 for(f = dirs.begin(), l = dirs.end(); f != l; ++f)
02827 {
02828 string const& cur = *f;
02829
02830 FileName tmp(cur);
02831
02832 tmp += string("/") + operand;
02833
02834 if(tmp.exists())
02835 {
02836 results->push_back(tmp);
02837 ++count;
02838 }
02839
02840 }
02841 }
02842
02843
02844
02845 {
02846 CppTagDB::Info* db = default_cpptags_db();
02847
02848 if(db)
02849 {
02850 vector<string> tmp;
02851
02852 db->findMatchingFiles(operand, tmp);
02853
02854 for(size_t i = 0; i < tmp.size(); ++i)
02855 {
02856 results->push_back(tmp[i]);
02857 ++count;
02858 }
02859
02860
02861 }
02862
02863 }
02864
02865 {
02866 EtagsDB* db = default_etags_db();
02867
02868 if(db && db->ok())
02869 {
02870 count += db->matching_files(operand, results);
02871 }
02872 }
02873
02874
02875 return count;
02876
02877 }
02878
02879 struct Is_Path_Separator
02880 {
02881 bool operator() (char c) const
02882 {
02883 return c == FileName::PATH_separator ;
02884 }
02885
02886 };
02887
02888
02889 FileName
02890 ViewerManager::
02891 find_file_in_standard_locations(FileName const &fragment, FileName const &directory)
02892 {
02893 FileName name;
02894
02895 if(fragment.is_absolute_path())
02896 {
02897
02898
02899 return fragment;
02900 }
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924 FileName specified_name(fragment);
02925 FileName local_dir_reference = directory + specified_name;
02926
02927 local_dir_reference.convert_to_absolute_path();
02928
02929 if( ! local_dir_reference.exists() )
02930 {
02931
02932 std::string cdpath = ProgramOptions::global_options_->getenv("SOURCEPATH");
02933
02934 if(cdpath.empty())
02935 cdpath = std::string(ProgramOptions::global_options_->getenv("CDPATH"));
02936
02937 bool found=false;
02938
02939 if(!cdpath.empty())
02940 {
02941
02942
02943
02944 if(directory.size())
02945 {
02946
02947 StrTool::stringlist_t splitpath;
02948
02949 Is_Path_Separator functor;
02950
02951 StrTool::parse_words(cdpath,
02952 &splitpath,
02953 2000000000U,
02954 functor
02955 );
02956
02957 StrTool::stringlist_t::iterator f = splitpath.begin();
02958 StrTool::stringlist_t::iterator l = splitpath.end();
02959
02960 while(f != l)
02961 {
02962 std::string &s = *f++;
02963
02964 if(s.size() > 2 && s[0] == '.' && ( s[1] == '.' || s[1] == '/' || s[1] == '\\' ))
02965 {
02966 s = directory + s;
02967 }
02968 }
02969
02970 cdpath.resize(0);
02971
02972 f = splitpath.begin();
02973
02974 while(f != l)
02975 {
02976 if(f != splitpath.begin())
02977 cdpath += ':';
02978
02979 cdpath += *f++;
02980 }
02981
02982 }
02983
02984
02985 }
02986
02987 if(!cdpath.empty())
02988 {
02989 FileName cd_path_location( FileName::find_file_in_path(specified_name, cdpath ) );
02990
02991 if(cd_path_location.size())
02992 {
02993 name = cd_path_location;
02994 specified_name = name;
02995 found=true;
02996 }
02997
02998 }
02999
03000 if(!found)
03001 {
03002 CppTagDB::Info * cpptags=(default_cpptags_db());
03003
03004 if(cpptags)
03005 {
03006 std::vector<std::string> matches;
03007
03008 std::string search_name;
03009
03010 size_t first_good_char = static_cast<std::string const &>(specified_name).find_first_not_of("..\\/");
03011
03012 if(first_good_char < specified_name.size())
03013 search_name = specified_name.substr(first_good_char, specified_name.size() - first_good_char);
03014 else
03015 search_name = specified_name;
03016
03017 cpptags->findRelativeFiles(search_name, matches);
03018
03019 if(!matches.empty())
03020 {
03021 std::string const & s = *matches.begin();
03022
03023 name = s;
03024 found=true;
03025 specified_name=name;
03026 }
03027 }
03028 }
03029
03030 if(!found)
03031 {
03032 EtagsDB* etags=(default_etags_db());
03033
03034 if(etags && etags->ok())
03035 {
03036 std::list<std::string> matches;
03037
03038 std::string search_name;
03039
03040 size_t first_good_char = static_cast<std::string const &>(specified_name).find_first_not_of("..\\/");
03041
03042 if(first_good_char < specified_name.size())
03043 search_name = specified_name.substr(first_good_char, specified_name.size() - first_good_char);
03044 else
03045 search_name = specified_name;
03046
03047 int count = etags->matching_files(search_name, &matches);
03048
03049 if(count)
03050 {
03051 std::string const & s = *matches.begin();
03052
03053 name = s;
03054 found=true;
03055 specified_name=name;
03056 }
03057 }
03058 }
03059 }
03060 else
03061 {
03062 specified_name=local_dir_reference;
03063
03064 name = specified_name;
03065
03066 }
03067
03068 return name;
03069
03070 }
03071
03072 void ViewerManager::findMatchingViewers(FileName namePattern, std::list<std::pair<Viewer*, FileName> > &viewers)
03073 {
03074 CXXTLS_FOREACH(vpentry &cur, viewers_)
03075 {
03076 FileName curFile(cur.second);
03077
03078 if( curFile.matches(namePattern) )
03079 {
03080 viewers.push_back(std::pair<Viewer*,FileName>(cur.first, cur.second) );
03081 }
03082 }
03083 }
03084
03085
03086
03087 Viewer* ViewerManager::most_recent_viewer()
03088 {
03089 if(order_.empty())
03090 {
03091 if(viewers_.empty())
03092 return 0;
03093
03094 return viewers_.back().first;
03095 }
03096
03097
03098
03099 MRU<std::string>::iterator mruPtr = order_.mostRecent();
03100
03101 if(mruPtr != order_.end())
03102 {
03103 std::string mru = *mruPtr;
03104
03105 return find_viewer(mru);
03106 }
03107
03108 return viewers_.back().first;
03109
03110
03111 }
03112
03113
03114
03115 }