Using GNU Readline; how can I add ncurses in the same program?

假如想象 提交于 2019-11-27 07:37:45
hlovdal

I have done some searching, and it seems like you are out of luck.

For ncurses alternatives there are SLang, Newt and Turbo Vision. Slang is much more than just screen handling and thus more complex, but maybe it can be used for your purpose?. Newt uses the screen handling and is much simpler, but too simple and single-threaded-mode for your purpose I think.

Turbo vision is the text mode graphics library from Borland, used by all their tools in the late 80s/early 90s. Borland released the source code when the market for that kind of thing diminished, and there is now a port for linux (side note, this project seems to have written its own turbo vision implementation). That port is not dead (there have been some cvs updates this year which compiled fine (the older releases did not)), but none of the TV examples I found were up to date and I did only got a few of them to compile before giving up on the rest. This is a bit of a shame, because TV was a lovely environment to use. TV is btw C++ (and I assume you are using C?).

For an alternative to readline, there is libkinput, which maybe works together with ncurses (it says it can use ncurses' terminfo. but I am not sure if that means that it can co-exists together with ncurses usage)?

Maybe one option is to run readline "externally" to your ncurses program using rlwrap?

I've now put together a simple example program on GitHub: https://github.com/ulfalizer/readline-and-ncurses.

It supports seamless and efficient terminal resizing and multibyte/combining/wide characters. The code has helpful comments.

Screenshot below:

This had me banging my head for a few hours, so just to save people Googling some pain:

If you're using ncurses' builtin SIGWINCH handler with KEY_RESIZE, be aware that readline sets the LINES and COLUMNS environment variables by default. These override any dynamic size calculation (usually with ioctl() TIOCGWINSZ) that ncurses would otherwise do, meaning you'll keep getting the initial terminal size even after resizing the terminal.

This can be prevented by setting rl_change_environment to 0 before initializing readline.

Update:

Here's some additional information I gleaned from the readline sources:

readline's SIGWINCH handling code (which is used if rl_catch_sigwinch is 1) does update LINES and COLUMNS, which seems like it should be sufficient for ncurses. However, when using the alternate readline interface (which makes most sense when combining readline with ncurses), the signal handlers (including the one for SIGWINCH) will only be installed for the duration of each rl_callback_read_char() call, meaning any terminal resize between two calls to rl_callback_read_char() will not be seen by readline.

I've achieved what you've described in a program of mine:

http://dpc.ucore.info/lab:xmppconsole

The following is the file handling io:

http://github.com/dpc/xmppconsole/blob/master/src/io.c

So it turns out that gdb uses both readline and ncurses. If you're interested in doing this, I recommend that you check out their implementation: http://sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c

I'm not sure which version you tried. As of today(2012.09.14) It is very simple, We just need to hook our custom function to following function pointers.

rl_getch_function
rl_redisplay_function
rl_completion_display_matches_hook

I did something reasonable here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!