1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2000-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 #  include "config.h"
28 #endif
29 
30 #if defined (USE_READLINE)
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 #include <readline/readline.h>
36 
37 #include "oct-rl-edit.h"
38 
39 #define OCTAVE_RL_SAVE_STRING(ss, s) \
40   static char *ss = 0; \
41  \
42   if (ss) \
43     { \
44       free (ss); \
45       ss = 0; \
46     } \
47  \
48   ss = malloc (strlen (s) + 1); \
49  \
50   if (ss) \
51     strcpy (ss, s)
52 
53 void
octave_rl_redisplay(void)54 octave_rl_redisplay (void)
55 {
56   rl_redisplay ();
57 }
58 
59 int
octave_rl_screen_height(void)60 octave_rl_screen_height (void)
61 {
62   int rows, cols;
63   rl_get_screen_size (&rows, &cols);
64   return rows;
65 }
66 
67 int
octave_rl_screen_width(void)68 octave_rl_screen_width (void)
69 {
70   int rows, cols;
71   rl_get_screen_size (&rows, &cols);
72   return cols;
73 }
74 
75 void
octave_rl_enable_paren_matching(int val)76 octave_rl_enable_paren_matching (int val)
77 {
78   rl_variable_bind ("blink-matching-paren", val ? "1" : "0");
79 }
80 
81 int
octave_rl_erase_empty_line(int val)82 octave_rl_erase_empty_line (int val)
83 {
84   int retval = rl_erase_empty_line;
85   rl_erase_empty_line = val;
86   return retval;
87 }
88 
89 /* It would be much simpler if we could just call _rl_clear_screen to
90    only clear the screen, but it is not a public function, and on some
91    systems, it is not exported from shared library versions of
92    readline, so we can't use it.
93 
94    Instead, temporarily redefine the redisplay function to do nothing.
95 
96    FIXME: It would be safer to do this when protected from interrupts... */
97 
98 static void
flush_stdout(void)99 flush_stdout (void)
100 {
101   fflush (stdout);
102 }
103 
104 void
octave_rl_clear_screen(int skip_redisplay)105 octave_rl_clear_screen (int skip_redisplay)
106 {
107   int ignore1 = 0;
108   int ignore2 = 0;
109 
110   if (skip_redisplay)
111     {
112       rl_voidfunc_t *saved_redisplay_function = rl_redisplay_function;
113 
114       rl_redisplay_function = flush_stdout;
115 
116       rl_clear_screen (ignore1, ignore2);
117 
118       rl_redisplay_function = saved_redisplay_function;
119     }
120   else
121     rl_clear_screen (ignore1, ignore2);
122 }
123 
124 void
octave_rl_resize_terminal(void)125 octave_rl_resize_terminal (void)
126 {
127   rl_resize_terminal ();
128 }
129 
130 void
octave_rl_set_screen_size(int ht,int wd)131 octave_rl_set_screen_size (int ht, int wd)
132 {
133   rl_set_screen_size (ht, wd);
134 }
135 
136 void
octave_rl_restore_terminal_state()137 octave_rl_restore_terminal_state ()
138 {
139   if (rl_deprep_term_function)
140     rl_deprep_term_function ();
141 }
142 
143 char *
octave_rl_copy_line(void)144 octave_rl_copy_line (void)
145 {
146   return rl_copy_text (0, rl_end);
147 }
148 
149 void
octave_rl_replace_line(const char * s,int clear_undo)150 octave_rl_replace_line (const char *s, int clear_undo)
151 {
152   rl_replace_line (s, clear_undo);
153 }
154 
155 void
octave_rl_kill_full_line(void)156 octave_rl_kill_full_line (void)
157 {
158   rl_kill_full_line (0, 0);
159 }
160 
161 void
octave_rl_insert_text(const char * s)162 octave_rl_insert_text (const char *s)
163 {
164   rl_insert_text (s);
165 }
166 
167 int
octave_rl_newline(int count,int key)168 octave_rl_newline (int count, int key)
169 {
170   return rl_newline (count, key);
171 }
172 
173 const char *
octave_rl_line_buffer(void)174 octave_rl_line_buffer (void)
175 {
176   return rl_line_buffer;
177 }
178 
179 int
octave_rl_point(void)180 octave_rl_point (void)
181 {
182   return rl_point;
183 }
184 
185 int
octave_rl_do_undo(void)186 octave_rl_do_undo (void)
187 {
188   return rl_do_undo ();
189 }
190 
191 void
octave_rl_clear_undo_list(void)192 octave_rl_clear_undo_list (void)
193 {
194   if (rl_undo_list)
195     {
196       rl_free_undo_list ();
197 
198       rl_undo_list = 0;
199     }
200 }
201 
202 void
octave_rl_set_name(const char * n)203 octave_rl_set_name (const char *n)
204 {
205   OCTAVE_RL_SAVE_STRING (nm, n);
206 
207   rl_readline_name = nm;
208 
209   /* Since we've already called rl_initialize, we need to re-read the
210      init file to take advantage of the conditional parsing feature
211      based on rl_readline_name; */
212 
213   rl_re_read_init_file (0, 0);
214 }
215 
216 char *
octave_rl_readline(const char * prompt)217 octave_rl_readline (const char *prompt)
218 {
219   return readline (prompt);
220 }
221 
222 void
octave_rl_set_input_stream(FILE * f)223 octave_rl_set_input_stream (FILE *f)
224 {
225   rl_instream = f;
226 }
227 
228 FILE *
octave_rl_get_input_stream(void)229 octave_rl_get_input_stream (void)
230 {
231   return rl_instream;
232 }
233 
234 void
octave_rl_set_output_stream(FILE * f)235 octave_rl_set_output_stream (FILE *f)
236 {
237   rl_outstream = f;
238 }
239 
240 FILE *
octave_rl_get_output_stream(void)241 octave_rl_get_output_stream (void)
242 {
243   return rl_outstream;
244 }
245 
246 void
octave_rl_read_init_file(const char * f)247 octave_rl_read_init_file (const char *f)
248 {
249   rl_read_init_file (f);
250 }
251 
252 void
octave_rl_re_read_init_file(void)253 octave_rl_re_read_init_file (void)
254 {
255   rl_re_read_init_file (0, 0);
256 }
257 
258 int
octave_rl_filename_completion_desired(int arg)259 octave_rl_filename_completion_desired (int arg)
260 {
261   int retval = rl_filename_completion_desired;
262   rl_filename_completion_desired = arg;
263   return retval;
264 }
265 
266 int
octave_rl_filename_quoting_desired(int arg)267 octave_rl_filename_quoting_desired (int arg)
268 {
269   int retval = rl_filename_quoting_desired;
270   rl_filename_quoting_desired = arg;
271   return retval;
272 }
273 
274 int
octave_rl_prefer_env_winsize(int arg)275 octave_rl_prefer_env_winsize (int arg)
276 {
277   int retval = rl_prefer_env_winsize;
278   rl_prefer_env_winsize = arg;
279   return retval;
280 }
281 
282 void
octave_rl_done(int arg)283 octave_rl_done (int arg)
284 {
285   rl_done = arg;
286 }
287 
288 char *
octave_rl_filename_completion_function(const char * text,int state)289 octave_rl_filename_completion_function (const char *text, int state)
290 {
291   return rl_filename_completion_function (text, state);
292 }
293 
294 void
octave_rl_set_basic_word_break_characters(const char * s)295 octave_rl_set_basic_word_break_characters (const char *s)
296 {
297   OCTAVE_RL_SAVE_STRING (ss, s);
298 
299   rl_basic_word_break_characters = ss;
300 }
301 
302 void
octave_rl_set_completer_word_break_characters(const char * s)303 octave_rl_set_completer_word_break_characters (const char *s)
304 {
305   OCTAVE_RL_SAVE_STRING (ss, s);
306 
307   rl_completer_word_break_characters = ss;
308 }
309 
310 char *
octave_rl_get_completer_word_break_characters(void)311 octave_rl_get_completer_word_break_characters (void)
312 {
313   return rl_completer_word_break_characters;
314 }
315 
316 void
octave_rl_set_completion_word_break_hook(rl_completion_hook_fcn_ptr f)317 octave_rl_set_completion_word_break_hook (rl_completion_hook_fcn_ptr f)
318 {
319   rl_completion_word_break_hook = f;
320 }
321 
322 void
octave_rl_set_basic_quote_characters(const char * s)323 octave_rl_set_basic_quote_characters (const char *s)
324 {
325   OCTAVE_RL_SAVE_STRING (ss, s);
326 
327   rl_basic_quote_characters = ss;
328 }
329 
330 void
octave_rl_set_filename_quote_characters(const char * s)331 octave_rl_set_filename_quote_characters (const char *s)
332 {
333   OCTAVE_RL_SAVE_STRING (ss, s);
334 
335   rl_filename_quote_characters = ss;
336 }
337 
338 void
octave_rl_set_completer_quote_characters(const char * s)339 octave_rl_set_completer_quote_characters (const char *s)
340 {
341   OCTAVE_RL_SAVE_STRING (ss, s);
342 
343   rl_completer_quote_characters = ss;
344 }
345 
346 void
octave_rl_set_completion_append_character(char c)347 octave_rl_set_completion_append_character (char c)
348 {
349   rl_completion_append_character = c;
350 }
351 
352 void
octave_rl_set_completion_function(rl_attempted_completion_fcn_ptr f)353 octave_rl_set_completion_function (rl_attempted_completion_fcn_ptr f)
354 {
355   rl_attempted_completion_function = f;
356 }
357 
358 void
octave_rl_set_quoting_function(rl_quoting_fcn_ptr f)359 octave_rl_set_quoting_function (rl_quoting_fcn_ptr f)
360 {
361   rl_filename_quoting_function = f;
362 }
363 
364 void
octave_rl_set_dequoting_function(rl_dequoting_fcn_ptr f)365 octave_rl_set_dequoting_function (rl_dequoting_fcn_ptr f)
366 {
367   rl_filename_dequoting_function = f;
368 }
369 
370 void
octave_rl_set_char_is_quoted_function(rl_char_is_quoted_fcn_ptr f)371 octave_rl_set_char_is_quoted_function (rl_char_is_quoted_fcn_ptr f)
372 {
373   rl_char_is_quoted_p = f;
374 }
375 
376 void
octave_rl_set_startup_hook(rl_startup_hook_fcn_ptr f)377 octave_rl_set_startup_hook (rl_startup_hook_fcn_ptr f)
378 {
379   rl_startup_hook = f;
380 }
381 
382 rl_startup_hook_fcn_ptr
octave_rl_get_startup_hook(void)383 octave_rl_get_startup_hook (void)
384 {
385   return rl_startup_hook;
386 }
387 
388 void
octave_rl_set_pre_input_hook(rl_pre_input_hook_fcn_ptr f)389 octave_rl_set_pre_input_hook (rl_pre_input_hook_fcn_ptr f)
390 {
391   rl_pre_input_hook = f;
392 }
393 
394 rl_pre_input_hook_fcn_ptr
octave_rl_get_pre_input_hook(void)395 octave_rl_get_pre_input_hook (void)
396 {
397   return rl_pre_input_hook;
398 }
399 
400 void
octave_rl_set_event_hook(rl_event_hook_fcn_ptr f)401 octave_rl_set_event_hook (rl_event_hook_fcn_ptr f)
402 {
403   rl_event_hook = f;
404 }
405 
406 rl_event_hook_fcn_ptr
octave_rl_get_event_hook(void)407 octave_rl_get_event_hook (void)
408 {
409   return rl_event_hook;
410 }
411 
412 char **
octave_rl_completion_matches(const char * text,rl_completer_fcn_ptr f)413 octave_rl_completion_matches (const char *text, rl_completer_fcn_ptr f)
414 {
415   return rl_completion_matches (text, f);
416 }
417 
418 char
octave_rl_prompt_start_ignore(void)419 octave_rl_prompt_start_ignore (void)
420 {
421   return RL_PROMPT_START_IGNORE;
422 }
423 
424 char
octave_rl_prompt_end_ignore(void)425 octave_rl_prompt_end_ignore (void)
426 {
427   return RL_PROMPT_END_IGNORE;
428 }
429 
430 void
octave_rl_add_defun(const char * name,rl_fcn_ptr f,int key)431 octave_rl_add_defun (const char *name, rl_fcn_ptr f, int key)
432 {
433   rl_add_defun (name, f, key);
434 }
435 
436 void
octave_rl_set_terminal_name(const char * term)437 octave_rl_set_terminal_name (const char *term)
438 {
439   OCTAVE_RL_SAVE_STRING (saved_term, term);
440 
441   rl_terminal_name = saved_term;
442 }
443 
444 void
octave_rl_initialize(void)445 octave_rl_initialize (void)
446 {
447 #if defined (__WIN32__) && ! defined (__CYGWIN__)
448   rl_catch_signals = 0;
449 #endif
450 
451   rl_initialize ();
452 }
453 
454 int
octave_rl_history_search_forward(int count,int ignore)455 octave_rl_history_search_forward (int count, int ignore)
456 {
457   return rl_history_search_forward (count, ignore);
458 }
459 
460 int
octave_rl_history_search_backward(int count,int ignore)461 octave_rl_history_search_backward (int count, int ignore)
462 {
463   return rl_history_search_backward (count, ignore);
464 }
465 
466 int
octave_rl_ctrl(char c)467 octave_rl_ctrl (char c)
468 {
469   return CTRL (c);
470 }
471 
472 int
octave_rl_meta(char c)473 octave_rl_meta (char c)
474 {
475   return META (c);
476 }
477 
478 void
octave_rl_recover_from_interrupt(void)479 octave_rl_recover_from_interrupt (void)
480 {
481   rl_free_line_state ();
482   rl_cleanup_after_signal ();
483   rl_reset_after_signal ();
484 }
485 
486 #endif
487