readline.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Thies C. Arntzen <thies@thieso.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* {{{ includes & prototypes */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_readline.h"
  24. #include "readline_cli.h"
  25. #if HAVE_LIBREADLINE || HAVE_LIBEDIT
  26. #ifndef HAVE_RL_COMPLETION_MATCHES
  27. #define rl_completion_matches completion_matches
  28. #endif
  29. #ifdef HAVE_LIBEDIT
  30. #include <editline/readline.h>
  31. #else
  32. #include <readline/readline.h>
  33. #include <readline/history.h>
  34. #endif
  35. PHP_FUNCTION(readline);
  36. PHP_FUNCTION(readline_add_history);
  37. PHP_FUNCTION(readline_info);
  38. PHP_FUNCTION(readline_clear_history);
  39. #ifndef HAVE_LIBEDIT
  40. PHP_FUNCTION(readline_list_history);
  41. #endif
  42. PHP_FUNCTION(readline_read_history);
  43. PHP_FUNCTION(readline_write_history);
  44. PHP_FUNCTION(readline_completion_function);
  45. #if HAVE_RL_CALLBACK_READ_CHAR
  46. PHP_FUNCTION(readline_callback_handler_install);
  47. PHP_FUNCTION(readline_callback_read_char);
  48. PHP_FUNCTION(readline_callback_handler_remove);
  49. PHP_FUNCTION(readline_redisplay);
  50. PHP_FUNCTION(readline_on_new_line);
  51. static zval _prepped_callback;
  52. #endif
  53. static zval _readline_completion;
  54. static zval _readline_array;
  55. PHP_MINIT_FUNCTION(readline);
  56. PHP_MSHUTDOWN_FUNCTION(readline);
  57. PHP_RSHUTDOWN_FUNCTION(readline);
  58. PHP_MINFO_FUNCTION(readline);
  59. /* }}} */
  60. /* {{{ arginfo */
  61. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline, 0, 0, 0)
  62. ZEND_ARG_INFO(0, prompt)
  63. ZEND_END_ARG_INFO()
  64. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_info, 0, 0, 0)
  65. ZEND_ARG_INFO(0, varname)
  66. ZEND_ARG_INFO(0, newvalue)
  67. ZEND_END_ARG_INFO()
  68. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_add_history, 0, 0, 1)
  69. ZEND_ARG_INFO(0, prompt)
  70. ZEND_END_ARG_INFO()
  71. ZEND_BEGIN_ARG_INFO(arginfo_readline_clear_history, 0)
  72. ZEND_END_ARG_INFO()
  73. #ifndef HAVE_LIBEDIT
  74. ZEND_BEGIN_ARG_INFO(arginfo_readline_list_history, 0)
  75. ZEND_END_ARG_INFO()
  76. #endif
  77. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_read_history, 0, 0, 0)
  78. ZEND_ARG_INFO(0, filename)
  79. ZEND_END_ARG_INFO()
  80. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_write_history, 0, 0, 0)
  81. ZEND_ARG_INFO(0, filename)
  82. ZEND_END_ARG_INFO()
  83. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_completion_function, 0, 0, 1)
  84. ZEND_ARG_INFO(0, funcname)
  85. ZEND_END_ARG_INFO()
  86. #if HAVE_RL_CALLBACK_READ_CHAR
  87. ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_callback_handler_install, 0, 0, 2)
  88. ZEND_ARG_INFO(0, prompt)
  89. ZEND_ARG_INFO(0, callback)
  90. ZEND_END_ARG_INFO()
  91. ZEND_BEGIN_ARG_INFO(arginfo_readline_callback_read_char, 0)
  92. ZEND_END_ARG_INFO()
  93. ZEND_BEGIN_ARG_INFO(arginfo_readline_callback_handler_remove, 0)
  94. ZEND_END_ARG_INFO()
  95. ZEND_BEGIN_ARG_INFO(arginfo_readline_redisplay, 0)
  96. ZEND_END_ARG_INFO()
  97. #if HAVE_RL_ON_NEW_LINE
  98. ZEND_BEGIN_ARG_INFO(arginfo_readline_on_new_line, 0)
  99. ZEND_END_ARG_INFO()
  100. #endif
  101. #endif
  102. /* }}} */
  103. /* {{{ module stuff */
  104. static const zend_function_entry php_readline_functions[] = {
  105. PHP_FE(readline, arginfo_readline)
  106. PHP_FE(readline_info, arginfo_readline_info)
  107. PHP_FE(readline_add_history, arginfo_readline_add_history)
  108. PHP_FE(readline_clear_history, arginfo_readline_clear_history)
  109. #ifndef HAVE_LIBEDIT
  110. PHP_FE(readline_list_history, arginfo_readline_list_history)
  111. #endif
  112. PHP_FE(readline_read_history, arginfo_readline_read_history)
  113. PHP_FE(readline_write_history, arginfo_readline_write_history)
  114. PHP_FE(readline_completion_function,arginfo_readline_completion_function)
  115. #if HAVE_RL_CALLBACK_READ_CHAR
  116. PHP_FE(readline_callback_handler_install, arginfo_readline_callback_handler_install)
  117. PHP_FE(readline_callback_read_char, arginfo_readline_callback_read_char)
  118. PHP_FE(readline_callback_handler_remove, arginfo_readline_callback_handler_remove)
  119. PHP_FE(readline_redisplay, arginfo_readline_redisplay)
  120. #endif
  121. #if HAVE_RL_ON_NEW_LINE
  122. PHP_FE(readline_on_new_line, arginfo_readline_on_new_line)
  123. #endif
  124. PHP_FE_END
  125. };
  126. zend_module_entry readline_module_entry = {
  127. STANDARD_MODULE_HEADER,
  128. "readline",
  129. php_readline_functions,
  130. PHP_MINIT(readline),
  131. PHP_MSHUTDOWN(readline),
  132. NULL,
  133. PHP_RSHUTDOWN(readline),
  134. PHP_MINFO(readline),
  135. PHP_READLINE_VERSION,
  136. STANDARD_MODULE_PROPERTIES
  137. };
  138. #ifdef COMPILE_DL_READLINE
  139. ZEND_GET_MODULE(readline)
  140. #endif
  141. PHP_MINIT_FUNCTION(readline)
  142. {
  143. #if HAVE_LIBREADLINE
  144. /* libedit don't need this call which set the tty in cooked mode */
  145. using_history();
  146. #endif
  147. ZVAL_UNDEF(&_readline_completion);
  148. #if HAVE_RL_CALLBACK_READ_CHAR
  149. ZVAL_UNDEF(&_prepped_callback);
  150. #endif
  151. return PHP_MINIT(cli_readline)(INIT_FUNC_ARGS_PASSTHRU);
  152. }
  153. PHP_MSHUTDOWN_FUNCTION(readline)
  154. {
  155. return PHP_MSHUTDOWN(cli_readline)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
  156. }
  157. PHP_RSHUTDOWN_FUNCTION(readline)
  158. {
  159. zval_ptr_dtor(&_readline_completion);
  160. ZVAL_UNDEF(&_readline_completion);
  161. #if HAVE_RL_CALLBACK_READ_CHAR
  162. if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
  163. rl_callback_handler_remove();
  164. zval_ptr_dtor(&_prepped_callback);
  165. ZVAL_UNDEF(&_prepped_callback);
  166. }
  167. #endif
  168. return SUCCESS;
  169. }
  170. PHP_MINFO_FUNCTION(readline)
  171. {
  172. PHP_MINFO(cli_readline)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
  173. }
  174. /* }}} */
  175. /* {{{ proto string readline([string prompt])
  176. Reads a line */
  177. PHP_FUNCTION(readline)
  178. {
  179. char *prompt = NULL;
  180. size_t prompt_len;
  181. char *result;
  182. if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &prompt, &prompt_len)) {
  183. RETURN_FALSE;
  184. }
  185. result = readline(prompt);
  186. if (! result) {
  187. RETURN_FALSE;
  188. } else {
  189. RETVAL_STRING(result);
  190. free(result);
  191. }
  192. }
  193. /* }}} */
  194. #define SAFE_STRING(s) ((s)?(char*)(s):"")
  195. /* {{{ proto mixed readline_info([string varname [, string newvalue]])
  196. Gets/sets various internal readline variables. */
  197. PHP_FUNCTION(readline_info)
  198. {
  199. char *what = NULL;
  200. zval *value = NULL;
  201. size_t what_len, oldval;
  202. char *oldstr;
  203. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sz", &what, &what_len, &value) == FAILURE) {
  204. return;
  205. }
  206. if (!what) {
  207. array_init(return_value);
  208. add_assoc_string(return_value,"line_buffer",SAFE_STRING(rl_line_buffer));
  209. add_assoc_long(return_value,"point",rl_point);
  210. #ifndef PHP_WIN32
  211. add_assoc_long(return_value,"end",rl_end);
  212. #endif
  213. #ifdef HAVE_LIBREADLINE
  214. add_assoc_long(return_value,"mark",rl_mark);
  215. add_assoc_long(return_value,"done",rl_done);
  216. add_assoc_long(return_value,"pending_input",rl_pending_input);
  217. add_assoc_string(return_value,"prompt",SAFE_STRING(rl_prompt));
  218. add_assoc_string(return_value,"terminal_name",(char *)SAFE_STRING(rl_terminal_name));
  219. add_assoc_str(return_value, "completion_append_character",
  220. rl_completion_append_character == 0
  221. ? ZSTR_EMPTY_ALLOC()
  222. : ZSTR_CHAR(rl_completion_append_character));
  223. add_assoc_bool(return_value,"completion_suppress_append",rl_completion_suppress_append);
  224. #endif
  225. #if HAVE_ERASE_EMPTY_LINE
  226. add_assoc_long(return_value,"erase_empty_line",rl_erase_empty_line);
  227. #endif
  228. #ifndef PHP_WIN32
  229. add_assoc_string(return_value,"library_version",(char *)SAFE_STRING(rl_library_version));
  230. #endif
  231. add_assoc_string(return_value,"readline_name",(char *)SAFE_STRING(rl_readline_name));
  232. add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over);
  233. } else {
  234. if (!strcasecmp(what,"line_buffer")) {
  235. oldstr = rl_line_buffer;
  236. if (value) {
  237. /* XXX if (rl_line_buffer) free(rl_line_buffer); */
  238. convert_to_string_ex(value);
  239. rl_line_buffer = strdup(Z_STRVAL_P(value));
  240. }
  241. RETVAL_STRING(SAFE_STRING(oldstr));
  242. } else if (!strcasecmp(what, "point")) {
  243. RETVAL_LONG(rl_point);
  244. #ifndef PHP_WIN32
  245. } else if (!strcasecmp(what, "end")) {
  246. RETVAL_LONG(rl_end);
  247. #endif
  248. #ifdef HAVE_LIBREADLINE
  249. } else if (!strcasecmp(what, "mark")) {
  250. RETVAL_LONG(rl_mark);
  251. } else if (!strcasecmp(what, "done")) {
  252. oldval = rl_done;
  253. if (value) {
  254. convert_to_long_ex(value);
  255. rl_done = Z_LVAL_P(value);
  256. }
  257. RETVAL_LONG(oldval);
  258. } else if (!strcasecmp(what, "pending_input")) {
  259. oldval = rl_pending_input;
  260. if (value) {
  261. convert_to_string_ex(value);
  262. rl_pending_input = Z_STRVAL_P(value)[0];
  263. }
  264. RETVAL_LONG(oldval);
  265. } else if (!strcasecmp(what, "prompt")) {
  266. RETVAL_STRING(SAFE_STRING(rl_prompt));
  267. } else if (!strcasecmp(what, "terminal_name")) {
  268. RETVAL_STRING((char *)SAFE_STRING(rl_terminal_name));
  269. } else if (!strcasecmp(what, "completion_suppress_append")) {
  270. oldval = rl_completion_suppress_append;
  271. if (value) {
  272. rl_completion_suppress_append = zend_is_true(value);
  273. }
  274. RETVAL_BOOL(oldval);
  275. } else if (!strcasecmp(what, "completion_append_character")) {
  276. oldval = rl_completion_append_character;
  277. if (value) {
  278. convert_to_string_ex(value)
  279. rl_completion_append_character = (int)Z_STRVAL_P(value)[0];
  280. }
  281. RETVAL_INTERNED_STR(
  282. oldval == 0 ? ZSTR_EMPTY_ALLOC() : ZSTR_CHAR(oldval));
  283. #endif
  284. #if HAVE_ERASE_EMPTY_LINE
  285. } else if (!strcasecmp(what, "erase_empty_line")) {
  286. oldval = rl_erase_empty_line;
  287. if (value) {
  288. convert_to_long_ex(value);
  289. rl_erase_empty_line = Z_LVAL_P(value);
  290. }
  291. RETVAL_LONG(oldval);
  292. #endif
  293. #ifndef PHP_WIN32
  294. } else if (!strcasecmp(what,"library_version")) {
  295. RETVAL_STRING((char *)SAFE_STRING(rl_library_version));
  296. #endif
  297. } else if (!strcasecmp(what, "readline_name")) {
  298. oldstr = (char*)rl_readline_name;
  299. if (value) {
  300. /* XXX if (rl_readline_name) free(rl_readline_name); */
  301. convert_to_string_ex(value);
  302. rl_readline_name = strdup(Z_STRVAL_P(value));
  303. }
  304. RETVAL_STRING(SAFE_STRING(oldstr));
  305. } else if (!strcasecmp(what, "attempted_completion_over")) {
  306. oldval = rl_attempted_completion_over;
  307. if (value) {
  308. convert_to_long_ex(value);
  309. rl_attempted_completion_over = Z_LVAL_P(value);
  310. }
  311. RETVAL_LONG(oldval);
  312. }
  313. }
  314. }
  315. /* }}} */
  316. /* {{{ proto bool readline_add_history(string prompt)
  317. Adds a line to the history */
  318. PHP_FUNCTION(readline_add_history)
  319. {
  320. char *arg;
  321. size_t arg_len;
  322. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
  323. return;
  324. }
  325. add_history(arg);
  326. RETURN_TRUE;
  327. }
  328. /* }}} */
  329. /* {{{ proto bool readline_clear_history(void)
  330. Clears the history */
  331. PHP_FUNCTION(readline_clear_history)
  332. {
  333. if (zend_parse_parameters_none() == FAILURE) {
  334. return;
  335. }
  336. #if HAVE_LIBEDIT
  337. /* clear_history is the only function where rl_initialize
  338. is not call to ensure correct allocation */
  339. using_history();
  340. #endif
  341. clear_history();
  342. RETURN_TRUE;
  343. }
  344. /* }}} */
  345. /* {{{ proto array readline_list_history(void)
  346. Lists the history */
  347. #ifndef HAVE_LIBEDIT
  348. PHP_FUNCTION(readline_list_history)
  349. {
  350. HIST_ENTRY **history;
  351. if (zend_parse_parameters_none() == FAILURE) {
  352. return;
  353. }
  354. history = history_list();
  355. array_init(return_value);
  356. if (history) {
  357. int i;
  358. for (i = 0; history[i]; i++) {
  359. add_next_index_string(return_value,history[i]->line);
  360. }
  361. }
  362. }
  363. #endif
  364. /* }}} */
  365. /* {{{ proto bool readline_read_history([string filename])
  366. Reads the history */
  367. PHP_FUNCTION(readline_read_history)
  368. {
  369. char *arg = NULL;
  370. size_t arg_len;
  371. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|p", &arg, &arg_len) == FAILURE) {
  372. return;
  373. }
  374. if (arg && php_check_open_basedir(arg)) {
  375. RETURN_FALSE;
  376. }
  377. /* XXX from & to NYI */
  378. if (read_history(arg)) {
  379. /* If filename is NULL, then read from `~/.history' */
  380. RETURN_FALSE;
  381. } else {
  382. RETURN_TRUE;
  383. }
  384. }
  385. /* }}} */
  386. /* {{{ proto bool readline_write_history([string filename])
  387. Writes the history */
  388. PHP_FUNCTION(readline_write_history)
  389. {
  390. char *arg = NULL;
  391. size_t arg_len;
  392. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|p", &arg, &arg_len) == FAILURE) {
  393. return;
  394. }
  395. if (arg && php_check_open_basedir(arg)) {
  396. RETURN_FALSE;
  397. }
  398. if (write_history(arg)) {
  399. RETURN_FALSE;
  400. } else {
  401. RETURN_TRUE;
  402. }
  403. }
  404. /* }}} */
  405. /* {{{ proto bool readline_completion_function(string funcname)
  406. Readline completion function? */
  407. static char *_readline_command_generator(const char *text, int state)
  408. {
  409. HashTable *myht = Z_ARRVAL(_readline_array);
  410. zval *entry;
  411. if (!state) {
  412. zend_hash_internal_pointer_reset(myht);
  413. }
  414. while ((entry = zend_hash_get_current_data(myht)) != NULL) {
  415. zend_hash_move_forward(myht);
  416. convert_to_string_ex(entry);
  417. if (strncmp (Z_STRVAL_P(entry), text, strlen(text)) == 0) {
  418. return (strdup(Z_STRVAL_P(entry)));
  419. }
  420. }
  421. return NULL;
  422. }
  423. static void _readline_string_zval(zval *ret, const char *str)
  424. {
  425. if (str) {
  426. ZVAL_STRING(ret, (char*)str);
  427. } else {
  428. ZVAL_NULL(ret);
  429. }
  430. }
  431. static void _readline_long_zval(zval *ret, long l)
  432. {
  433. ZVAL_LONG(ret, l);
  434. }
  435. static char **_readline_completion_cb(const char *text, int start, int end)
  436. {
  437. zval params[3];
  438. char **matches = NULL;
  439. _readline_string_zval(&params[0], text);
  440. _readline_long_zval(&params[1], start);
  441. _readline_long_zval(&params[2], end);
  442. if (call_user_function(CG(function_table), NULL, &_readline_completion, &_readline_array, 3, params) == SUCCESS) {
  443. if (Z_TYPE(_readline_array) == IS_ARRAY) {
  444. if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
  445. matches = rl_completion_matches(text,_readline_command_generator);
  446. } else {
  447. matches = malloc(sizeof(char *) * 2);
  448. if (!matches) {
  449. return NULL;
  450. }
  451. matches[0] = strdup("");
  452. matches[1] = NULL;
  453. }
  454. }
  455. }
  456. zval_ptr_dtor(&params[0]);
  457. zval_ptr_dtor(&_readline_array);
  458. return matches;
  459. }
  460. PHP_FUNCTION(readline_completion_function)
  461. {
  462. zval *arg;
  463. if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg)) {
  464. RETURN_FALSE;
  465. }
  466. if (!zend_is_callable(arg, 0, NULL)) {
  467. zend_string *name = zend_get_callable_name(arg);
  468. php_error_docref(NULL, E_WARNING, "%s is not callable", ZSTR_VAL(name));
  469. zend_string_release_ex(name, 0);
  470. RETURN_FALSE;
  471. }
  472. zval_ptr_dtor(&_readline_completion);
  473. ZVAL_COPY(&_readline_completion, arg);
  474. rl_attempted_completion_function = _readline_completion_cb;
  475. if (rl_attempted_completion_function == NULL) {
  476. RETURN_FALSE;
  477. }
  478. RETURN_TRUE;
  479. }
  480. /* }}} */
  481. #if HAVE_RL_CALLBACK_READ_CHAR
  482. static void php_rl_callback_handler(char *the_line)
  483. {
  484. zval params[1];
  485. zval dummy;
  486. ZVAL_NULL(&dummy);
  487. _readline_string_zval(&params[0], the_line);
  488. call_user_function(CG(function_table), NULL, &_prepped_callback, &dummy, 1, params);
  489. zval_ptr_dtor(&params[0]);
  490. zval_ptr_dtor(&dummy);
  491. }
  492. /* {{{ proto void readline_callback_handler_install(string prompt, mixed callback)
  493. Initializes the readline callback interface and terminal, prints the prompt and returns immediately */
  494. PHP_FUNCTION(readline_callback_handler_install)
  495. {
  496. zval *callback;
  497. char *prompt;
  498. size_t prompt_len;
  499. if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &prompt, &prompt_len, &callback)) {
  500. return;
  501. }
  502. if (!zend_is_callable(callback, 0, NULL)) {
  503. zend_string *name = zend_get_callable_name(callback);
  504. php_error_docref(NULL, E_WARNING, "%s is not callable", ZSTR_VAL(name));
  505. zend_string_release_ex(name, 0);
  506. RETURN_FALSE;
  507. }
  508. if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
  509. rl_callback_handler_remove();
  510. zval_ptr_dtor(&_prepped_callback);
  511. }
  512. ZVAL_COPY(&_prepped_callback, callback);
  513. rl_callback_handler_install(prompt, php_rl_callback_handler);
  514. RETURN_TRUE;
  515. }
  516. /* }}} */
  517. /* {{{ proto void readline_callback_read_char()
  518. Informs the readline callback interface that a character is ready for input */
  519. PHP_FUNCTION(readline_callback_read_char)
  520. {
  521. if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
  522. rl_callback_read_char();
  523. }
  524. }
  525. /* }}} */
  526. /* {{{ proto bool readline_callback_handler_remove()
  527. Removes a previously installed callback handler and restores terminal settings */
  528. PHP_FUNCTION(readline_callback_handler_remove)
  529. {
  530. if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
  531. rl_callback_handler_remove();
  532. zval_ptr_dtor(&_prepped_callback);
  533. ZVAL_UNDEF(&_prepped_callback);
  534. RETURN_TRUE;
  535. }
  536. RETURN_FALSE;
  537. }
  538. /* }}} */
  539. /* {{{ proto void readline_redisplay(void)
  540. Ask readline to redraw the display */
  541. PHP_FUNCTION(readline_redisplay)
  542. {
  543. #if HAVE_LIBEDIT
  544. /* seems libedit doesn't take care of rl_initialize in rl_redisplay
  545. * see bug #72538 */
  546. using_history();
  547. #endif
  548. rl_redisplay();
  549. }
  550. /* }}} */
  551. #endif
  552. #if HAVE_RL_ON_NEW_LINE
  553. /* {{{ proto void readline_on_new_line(void)
  554. Inform readline that the cursor has moved to a new line */
  555. PHP_FUNCTION(readline_on_new_line)
  556. {
  557. rl_on_new_line();
  558. }
  559. /* }}} */
  560. #endif
  561. #endif /* HAVE_LIBREADLINE */
  562. /*
  563. * Local variables:
  564. * tab-width: 4
  565. * c-basic-offset: 4
  566. * End:
  567. */