00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cstring>
00028
00029 #include <iostream>
00030 #include <string>
00031
00032 #include "cmd-edit.h"
00033 #include "cmd-hist.h"
00034 #include "lo-error.h"
00035 #include "str-vec.h"
00036
00037 command_history *command_history::instance = 0;
00038
00039 #if defined (USE_READLINE)
00040
00041 #include <cstdlib>
00042
00043 #ifdef HAVE_FCNTL_H
00044 #include <fcntl.h>
00045 #endif
00046
00047 #ifdef HAVE_UNISTD_H
00048 #ifdef HAVE_SYS_TYPES_H
00049 #include <sys/types.h>
00050 #endif
00051 #include <unistd.h>
00052 #endif
00053
00054 #include "oct-rl-hist.h"
00055
00056 #include "file-stat.h"
00057
00058 class
00059 gnu_history : public command_history
00060 {
00061 public:
00062
00063 gnu_history (void)
00064 : command_history (), mark (0) { }
00065
00066 ~gnu_history (void) { }
00067
00068 void do_add (const std::string&);
00069
00070 void do_remove (int);
00071
00072 int do_where (void);
00073
00074 int do_length (void);
00075
00076 int do_max_input_history (void);
00077
00078 int do_base (void);
00079
00080 int do_current_number (void);
00081
00082 void do_stifle (int);
00083
00084 int do_unstifle (void);
00085
00086 int do_is_stifled (void);
00087
00088 void do_set_mark (int);
00089
00090 int do_goto_mark (void);
00091
00092 void do_read (const std::string&, bool);
00093
00094 void do_read_range (const std::string&, int, int, bool);
00095
00096 void do_write (const std::string&);
00097
00098 void do_append (const std::string&);
00099
00100 void do_truncate_file (const std::string&, int);
00101
00102 string_vector do_list (int, bool);
00103
00104 std::string do_get_entry (int);
00105
00106 void do_replace_entry (int, const std::string&);
00107
00108 void do_clean_up_and_save (const std::string&, int);
00109
00110 private:
00111
00112 int mark;
00113 };
00114
00115 void
00116 gnu_history::do_add (const std::string& s)
00117 {
00118 if (! do_ignoring_entries ())
00119 {
00120 if (s.empty ()
00121 || (s.length () == 1 && (s[0] == '\r' || s[0] == '\n')))
00122 return;
00123
00124 ::octave_add_history (s.c_str ());
00125
00126 lines_this_session++;
00127 }
00128 }
00129
00130 void
00131 gnu_history::do_remove (int n)
00132 {
00133 ::octave_remove_history (n);
00134 }
00135
00136 int
00137 gnu_history::do_where (void)
00138 {
00139 return ::octave_where_history ();
00140 }
00141
00142 int
00143 gnu_history::do_length (void)
00144 {
00145 return ::octave_history_length ();
00146 }
00147
00148 int
00149 gnu_history::do_max_input_history (void)
00150 {
00151 return ::octave_max_input_history ();
00152 }
00153
00154 int
00155 gnu_history::do_base (void)
00156 {
00157 return ::octave_history_base ();
00158 }
00159
00160 int
00161 gnu_history::do_current_number (void)
00162 {
00163 return (xsize > 0) ? do_base () + do_where () : -1;
00164 }
00165
00166 void
00167 gnu_history::do_stifle (int n)
00168 {
00169 ::octave_stifle_history (n);
00170 }
00171
00172 int
00173 gnu_history::do_unstifle (void)
00174 {
00175 return ::octave_unstifle_history ();
00176 }
00177
00178 int
00179 gnu_history::do_is_stifled (void)
00180 {
00181 return ::octave_history_is_stifled ();
00182 }
00183
00184 void
00185 gnu_history::do_set_mark (int n)
00186 {
00187 mark = n;
00188 }
00189
00190 int
00191 gnu_history::do_goto_mark (void)
00192 {
00193 if (mark)
00194 {
00195 char *line = ::octave_history_goto_mark (mark);
00196
00197 if (line)
00198 {
00199 command_editor::insert_text (line);
00200
00201 command_editor::clear_undo_list ();
00202 }
00203 }
00204
00205 mark = 0;
00206
00207
00208 command_editor::restore_startup_hook ();
00209
00210 return 0;
00211 }
00212
00213 void
00214 gnu_history::do_read (const std::string& f, bool must_exist)
00215 {
00216 if (! f.empty ())
00217 {
00218 int status = ::octave_read_history (f.c_str ());
00219
00220 if (status != 0 && must_exist)
00221 error (status);
00222 else
00223 {
00224 lines_in_file = do_where ();
00225
00226 ::octave_using_history ();
00227 }
00228 }
00229 else
00230 error ("gnu_history::read: missing file name");
00231 }
00232
00233 void
00234 gnu_history::do_read_range (const std::string& f, int from, int to,
00235 bool must_exist)
00236 {
00237 if (from < 0)
00238 from = lines_in_file;
00239
00240 if (! f.empty ())
00241 {
00242 int status = ::octave_read_history_range (f.c_str (), from, to);
00243
00244 if (status != 0 && must_exist)
00245 error (status);
00246 else
00247 {
00248 lines_in_file = do_where ();
00249
00250 ::octave_using_history ();
00251 }
00252 }
00253 else
00254 error ("gnu_history::read_range: missing file name");
00255 }
00256
00257 void
00258 gnu_history::do_write (const std::string& f_arg)
00259 {
00260 std::string f = f_arg;
00261
00262 if (f.empty ())
00263 f = xfile;
00264
00265 if (! f.empty ())
00266 {
00267 int status = ::octave_write_history (f.c_str ());
00268
00269 if (status != 0)
00270 error (status);
00271 }
00272 else
00273 error ("gnu_history::write: missing file name");
00274 }
00275
00276 void
00277 gnu_history::do_append (const std::string& f_arg)
00278 {
00279 if (lines_this_session)
00280 {
00281 if (lines_this_session < do_where ())
00282 {
00283
00284
00285 std::string f = f_arg;
00286
00287 if (f.empty ())
00288 f = xfile;
00289
00290 if (! f.empty ())
00291 {
00292 file_stat fs (f);
00293
00294 if (! fs)
00295 {
00296 int tem;
00297
00298 tem = open (f.c_str (), O_CREAT, 0666);
00299 close (tem);
00300 }
00301
00302 int status
00303 = ::octave_append_history (lines_this_session, f.c_str ());
00304
00305 if (status != 0)
00306 error (status);
00307 else
00308 lines_in_file += lines_this_session;
00309
00310 lines_this_session = 0;
00311 }
00312 else
00313 error ("gnu_history::append: missing file name");
00314 }
00315 }
00316 }
00317
00318 void
00319 gnu_history::do_truncate_file (const std::string& f_arg, int n)
00320 {
00321 std::string f = f_arg;
00322
00323 if (f.empty ())
00324 f = xfile;
00325
00326 if (! f.empty ())
00327 ::octave_history_truncate_file (f.c_str (), n);
00328 else
00329 error ("gnu_history::truncate_file: missing file name");
00330 }
00331
00332 string_vector
00333 gnu_history::do_list (int limit, bool number_lines)
00334 {
00335 string_vector retval;
00336
00337 if (limit)
00338 retval = ::octave_history_list (limit, number_lines);
00339
00340 return retval;
00341 }
00342
00343 std::string
00344 gnu_history::do_get_entry (int n)
00345 {
00346 std::string retval;
00347
00348 char *line = ::octave_history_get (do_base () + n);
00349
00350 if (line)
00351 retval = line;
00352
00353 return retval;
00354 }
00355
00356 void
00357 gnu_history::do_replace_entry (int which, const std::string& line)
00358 {
00359 ::octave_replace_history_entry (which, line.c_str ());
00360 }
00361
00362 void
00363 gnu_history::do_clean_up_and_save (const std::string& f_arg, int n)
00364 {
00365 std::string f = f_arg;
00366
00367 if (f.empty ())
00368 f = xfile;
00369
00370 if (! f.empty ())
00371 {
00372 if (n < 0)
00373 n = xsize;
00374
00375 stifle (n);
00376
00377 do_write (f.c_str ());
00378 }
00379 else
00380 error ("gnu_history::clean_up_and_save: missing file name");
00381 }
00382
00383 #endif
00384
00385 bool
00386 command_history::instance_ok (void)
00387 {
00388 bool retval = true;
00389
00390 if (! instance)
00391 make_command_history ();
00392
00393 if (! instance)
00394 {
00395 (*current_liboctave_error_handler)
00396 ("unable to create command history object!");
00397
00398 retval = false;
00399 }
00400
00401 return retval;
00402 }
00403
00404 void
00405 command_history::make_command_history (void)
00406 {
00407 #if defined (USE_READLINE)
00408 instance = new gnu_history ();
00409 #else
00410 instance = new command_history ();
00411 #endif
00412 }
00413
00414 void
00415 command_history::set_file (const std::string& f)
00416 {
00417 if (instance_ok ())
00418 instance->do_set_file (f);
00419 }
00420
00421 std::string
00422 command_history::file (void)
00423 {
00424 return (instance_ok ())
00425 ? instance->do_file () : std::string ();
00426 }
00427
00428 void
00429 command_history::set_size (int n)
00430 {
00431 if (instance_ok ())
00432 instance->do_set_size (n);
00433 }
00434
00435 int
00436 command_history::size (void)
00437 {
00438 return (instance_ok ())
00439 ? instance->do_size () : 0;
00440 }
00441
00442 void
00443 command_history::ignore_entries (bool flag)
00444 {
00445 if (instance_ok ())
00446 instance->do_ignore_entries (flag);
00447 }
00448
00449 bool
00450 command_history::ignoring_entries (void)
00451 {
00452 return (instance_ok ())
00453 ? instance->do_ignoring_entries () : false;
00454 }
00455
00456 void
00457 command_history::add (const std::string& s)
00458 {
00459 if (instance_ok ())
00460 instance->do_add (s);
00461 }
00462
00463 void
00464 command_history::remove (int n)
00465 {
00466 if (instance_ok ())
00467 instance->do_remove (n);
00468 }
00469
00470 int
00471 command_history::where (void)
00472 {
00473 return (instance_ok ())
00474 ? instance->do_where () : 0;
00475 }
00476
00477 int
00478 command_history::length (void)
00479 {
00480 return (instance_ok ())
00481 ? instance->do_length () : 0;
00482 }
00483
00484 int
00485 command_history::max_input_history (void)
00486 {
00487 return (instance_ok ())
00488 ? instance->do_max_input_history () : 0;
00489 }
00490
00491 int
00492 command_history::base (void)
00493 {
00494 return (instance_ok ())
00495 ? instance->do_base () : 0;
00496 }
00497
00498 int
00499 command_history::current_number (void)
00500 {
00501 return (instance_ok ())
00502 ? instance->do_current_number () : 0;
00503 }
00504
00505 void
00506 command_history::stifle (int n)
00507 {
00508 if (instance_ok ())
00509 instance->do_stifle (n);
00510 }
00511
00512 int
00513 command_history::unstifle (void)
00514 {
00515 return (instance_ok ())
00516 ? instance->do_unstifle () : 0;
00517 }
00518
00519 int
00520 command_history::is_stifled (void)
00521 {
00522 return (instance_ok ())
00523 ? instance->do_is_stifled () : 0;
00524 }
00525
00526 void
00527 command_history::set_mark (int n)
00528 {
00529 if (instance_ok ())
00530 instance->do_set_mark (n);
00531 }
00532
00533 int
00534 command_history::goto_mark (void)
00535 {
00536 return (instance_ok ())
00537 ? instance->do_goto_mark () : 0;
00538 }
00539
00540 void
00541 command_history::read (bool must_exist)
00542 {
00543 read (file (), must_exist);
00544 }
00545
00546 void
00547 command_history::read (const std::string& f, bool must_exist)
00548 {
00549 if (instance_ok ())
00550 instance->do_read (f, must_exist);
00551 }
00552
00553 void
00554 command_history::read_range (int from, int to, bool must_exist)
00555 {
00556 read_range (file (), from, to, must_exist);
00557 }
00558
00559 void
00560 command_history::read_range (const std::string& f, int from, int to,
00561 bool must_exist)
00562 {
00563 if (instance_ok ())
00564 instance->do_read_range (f, from, to, must_exist);
00565 }
00566
00567 void
00568 command_history::write (const std::string& f)
00569 {
00570 if (instance_ok ())
00571 instance->do_write (f);
00572 }
00573
00574 void
00575 command_history::append (const std::string& f)
00576 {
00577 if (instance_ok ())
00578 instance->do_append (f);
00579 }
00580
00581 void
00582 command_history::truncate_file (const std::string& f, int n)
00583 {
00584 if (instance_ok ())
00585 instance->do_truncate_file (f, n);
00586 }
00587
00588 string_vector
00589 command_history::list (int limit, bool number_lines)
00590 {
00591 return (instance_ok ())
00592 ? instance->do_list (limit, number_lines) : string_vector ();
00593 }
00594
00595 std::string
00596 command_history::get_entry (int n)
00597 {
00598 return (instance_ok ())
00599 ? instance->do_get_entry (n) : std::string ();
00600 }
00601
00602 void
00603 command_history::replace_entry (int which, const std::string& line)
00604 {
00605 if (instance_ok ())
00606 instance->do_replace_entry (which, line);
00607 }
00608
00609 void
00610 command_history::clean_up_and_save (const std::string& f, int n)
00611 {
00612 if (instance_ok ())
00613 instance->do_clean_up_and_save (f, n);
00614 }
00615
00616 void
00617 command_history::do_set_file (const std::string& f)
00618 {
00619 xfile = f;
00620 }
00621
00622 std::string
00623 command_history::do_file (void)
00624 {
00625 return xfile;
00626 }
00627
00628 void
00629 command_history::do_set_size (int n)
00630 {
00631 xsize = n;
00632 }
00633
00634 int
00635 command_history::do_size (void)
00636 {
00637 return xsize;
00638 }
00639
00640 void
00641 command_history::do_ignore_entries (bool flag)
00642 {
00643 ignoring_additions = flag;
00644 }
00645
00646 bool
00647 command_history::do_ignoring_entries (void)
00648 {
00649 return ignoring_additions;
00650 }
00651
00652 void
00653 command_history::do_add (const std::string&)
00654 {
00655 }
00656
00657 void
00658 command_history::do_remove (int)
00659 {
00660 }
00661
00662 int
00663 command_history::do_where (void)
00664 {
00665 return 0;
00666 }
00667
00668 int
00669 command_history::do_length (void)
00670 {
00671 return 0;
00672 }
00673
00674 int
00675 command_history::do_max_input_history (void)
00676 {
00677 return 0;
00678 }
00679
00680 int
00681 command_history::do_base (void)
00682 {
00683 return 0;
00684 }
00685
00686 int
00687 command_history::do_current_number (void)
00688 {
00689 return (xsize > 0) ? do_base () + do_where () : -1;
00690 }
00691
00692 void
00693 command_history::do_stifle (int)
00694 {
00695 }
00696
00697 int
00698 command_history::do_unstifle (void)
00699 {
00700 return -1;
00701 }
00702
00703 int
00704 command_history::do_is_stifled (void)
00705 {
00706 return 0;
00707 }
00708
00709 void
00710 command_history::do_set_mark (int)
00711 {
00712 }
00713
00714 int
00715 command_history::do_goto_mark (void)
00716 {
00717 return 0;
00718 }
00719
00720 void
00721 command_history::do_read (const std::string& f, bool)
00722 {
00723 if (f.empty ())
00724 error ("command_history::read: missing file name");
00725 }
00726
00727 void
00728 command_history::do_read_range (const std::string& f, int, int, bool)
00729 {
00730 if (f.empty ())
00731 error ("command_history::read_range: missing file name");
00732 }
00733
00734 void
00735 command_history::do_write (const std::string& f_arg)
00736 {
00737 std::string f = f_arg;
00738
00739 if (f.empty ())
00740 f = xfile;
00741
00742 if (f.empty ())
00743 error ("command_history::write: missing file name");
00744 }
00745
00746 void
00747 command_history::do_append (const std::string& f_arg)
00748 {
00749 if (lines_this_session)
00750 {
00751 if (lines_this_session < do_where ())
00752 {
00753
00754
00755 std::string f = f_arg;
00756
00757 if (f.empty ())
00758 f = xfile;
00759
00760 if (f.empty ())
00761 error ("command_history::append: missing file name");
00762 }
00763 }
00764 }
00765
00766 void
00767 command_history::do_truncate_file (const std::string& f_arg, int)
00768 {
00769 std::string f = f_arg;
00770
00771 if (f.empty ())
00772 f = xfile;
00773
00774 if (f.empty ())
00775 error ("command_history::truncate_file: missing file name");
00776 }
00777
00778 string_vector
00779 command_history::do_list (int, bool)
00780 {
00781 return string_vector ();
00782 }
00783
00784 std::string
00785 command_history::do_get_entry (int)
00786 {
00787 return std::string ();
00788 }
00789
00790 void
00791 command_history::do_replace_entry (int, const std::string&)
00792 {
00793 }
00794
00795 void
00796 command_history::do_clean_up_and_save (const std::string& f_arg, int)
00797 {
00798 std::string f = f_arg;
00799
00800 if (f.empty ())
00801 f = xfile;
00802
00803 if (f.empty ())
00804 error ("command_history::clean_up_and_save: missing file name");
00805 }
00806
00807 void
00808 command_history::error (int err_num)
00809 {
00810 (*current_liboctave_error_handler) ("%s", strerror (err_num));
00811 }
00812
00813 void
00814 command_history::error (const std::string& s)
00815 {
00816 (*current_liboctave_error_handler) ("%s", s.c_str ());
00817 }
00818
00819
00820
00821
00822
00823