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