table of contents
- NAME
- SYNOPSIS
- DESCRIPTION
- AN EXAMPLE
- THE FUNCTIONS USED IN THE EXAMPLE
- THE RETURN STATUS OF GL_GET_LINE
- OPTIONAL PROMPT FORMATTING
- ALTERNATE CONFIGURATION SOURCES
- CUSTOMIZED WORD COMPLETION
- ADDING COMPLETION ACTIONS
- DEFINING CUSTOM ACTIONS
- HISTORY FILES
- MULTIPLE HISTORY LISTS
- DISPLAYING HISTORY
- LOOKING UP HISTORY
- MANUAL HISTORY ARCHIVAL
- MISCELLANEOUS HISTORY CONFIGURATION
- QUERYING HISTORY INFORMATION
- CHANGING TERMINALS
- EXTERNAL EVENT HANDLING
- SETTING AN INACTIVITY TIMEOUT
- SIGNAL HANDLING DEFAULTS
- CUSTOMIZED SIGNAL HANDLING
- RELIABLE SIGNAL HANDLING
- THE TERMINAL SIZE
- HIDING WHAT YOU TYPE
- SINGLE CHARACTER QUERIES
- READING RAW CHARACTERS
- CLEARING THE TERMINAL
- DISPLAYING TEXT DYNAMICALLY
- CALLBACK FUNCTION FACILITIES
- INTERNATIONAL CHARACTER SETS
- THREAD SAFETY
- FILES
- SEE ALSO
- AUTHOR
other versions
- wheezy 1.6.1-5
| gl_get_line(3) | Library Functions Manual | gl_get_line(3) |
NAME¶
gl_get_line, new_GetLine, del_GetLine, gl_customize_completion, gl_change_terminal, gl_configure_getline, gl_load_history, gl_save_history, gl_group_history, gl_show_history, gl_watch_fd, gl_inactivity_timeout, gl_terminal_size, gl_set_term_size, gl_resize_history, gl_limit_history, gl_clear_history, gl_toggle_history, gl_lookup_history, gl_state_of_history, gl_range_of_history, gl_size_of_history, gl_echo_mode, gl_replace_prompt, gl_prompt_style, gl_ignore_signal, gl_trap_signal, gl_last_signal, gl_completion_action, gl_display_text, gl_return_status, gl_error_message, gl_catch_blocked, gl_list_signals, gl_bind_keyseq, gl_erase_terminal, gl_automatic_history, gl_append_history, gl_query_char, gl_read_char - allow the user to compose an input lineSYNOPSIS¶
#include <stdio.h>
#include <libtecla.h>
GetLine *new_GetLine(size_t linelen, size_t histlen);
GetLine *del_GetLine(GetLine *gl);
char *gl_get_line(GetLine *gl, const char *prompt,
const char *start_line, int start_pos);
int gl_query_char(GetLine *gl, const char *prompt,
char defchar);
int gl_read_char(GetLine *gl);
int gl_customize_completion(GetLine *gl, void *data,
CplMatchFn *match_fn);
int gl_change_terminal(GetLine *gl, FILE *input_fp,
FILE *output_fp, const char *term);
int gl_configure_getline(GetLine *gl,
const char *app_string,
const char *app_file,
const char *user_file);
int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin,
const char *keyseq, const char *action);
int gl_save_history(GetLine *gl, const char *filename,
const char *comment, int max_lines);
int gl_load_history(GetLine *gl, const char *filename,
const char *comment);
int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
GlFdEventFn *callback, void *data);
int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback,
void *data, unsigned long sec,
unsigned long nsec);
int gl_group_history(GetLine *gl, unsigned stream);
int gl_show_history(GetLine *gl, FILE *fp,
const char *fmt, int all_groups,
int max_lines);
int gl_resize_history(GetLine *gl, size_t bufsize);
void gl_limit_history(GetLine *gl, int max_lines);
void gl_clear_history(GetLine *gl, int all_groups);
void gl_toggle_history(GetLine *gl, int enable);
GlTerminalSize gl_terminal_size(GetLine *gl,
int def_ncolumn,
int def_nline);
int gl_set_term_size(GetLine *gl, int ncolumn, int nline);
int gl_lookup_history(GetLine *gl, unsigned long id,
GlHistoryLine *hline);
void gl_state_of_history(GetLine *gl,
GlHistoryState *state);
void gl_range_of_history(GetLine *gl,
GlHistoryRange *range);
void gl_size_of_history(GetLine *gl, GlHistorySize *size);
void gl_echo_mode(GetLine *gl, int enable);
void gl_replace_prompt(GetLine *gl, const char *prompt);
void gl_prompt_style(GetLine *gl, GlPromptStyle style);
int gl_ignore_signal(GetLine *gl, int signo);
int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
GlAfterSignal after, int errno_value);
int gl_last_signal(GetLine *gl);
int gl_completion_action(GetLine *gl,
void *data, CplMatchFn *match_fn,
int list_only, const char *name,
const char *keyseq);
int gl_register_action(GetLine *gl, void *data,
GlActionFn *fn, const char *name,
const char *keyseq);
int gl_display_text(GetLine *gl, int indentation,
const char *prefix,
const char *suffix, int fill_char,
int def_width, int start,
const char *string);
GlReturnStatus gl_return_status(GetLine *gl);
const char *gl_error_message(GetLine *gl, char *buff,
size_t n);
void gl_catch_blocked(GetLine *gl);
int gl_list_signals(GetLine *gl, sigset_t *set);
int gl_append_history(GetLine *gl, const char *line);
int gl_automatic_history(GetLine *gl, int enable);
DESCRIPTION¶
The gl_get_line() function is part of the tecla library (see the libtecla(3) man page). If the user is typing at a terminal, each call prompts them for an line of input, then provides interactive editing facilities, similar to those of the unix tcsh shell. In addition to simple command-line editing, it supports recall of previously entered command lines, TAB completion of file names, and in-line wild-card expansion of filenames. Documentation of both the user-level command-line editing features and all user configuration options, can be found in the tecla(7) man page. This man page concerns itself with documentation for programmers interested in using this library in their application.AN EXAMPLE¶
The following shows a complete example of how to use the gl_get_line() function to get input from the user: #include <stdio.h>
#include <locale.h>
#include <libtecla.h>
int main(int argc, char *argv[])
{
char *line; /* The line that the user typed */
GetLine *gl; /* The gl_get_line() resource object */
setlocale(LC_CTYPE, ""); /* Adopt the user's choice */
/* of character set. */
gl = new_GetLine(1024, 2048);
if(!gl)
return 1;
while((line=gl_get_line(gl, "$ ", NULL, -1)) != NULL &&
strcmp(line, "exit\n") != 0)
printf("You typed: %s\n", line);
gl = del_GetLine(gl);
return 0;
}
THE FUNCTIONS USED IN THE EXAMPLE¶
The descriptions of the functions used in the example are as follows:GetLine *new_GetLine(size_t linelen, size_t histlen)
GetLine *del_GetLine(GetLine *gl)
char *gl_get_line(GetLine *gl, const char *prompt,
const char *start_line, int start_pos);
THE RETURN STATUS OF GL_GET_LINE¶
As described above, the gl_get_line() function has two possible return values; a pointer to the completed input line, or NULL. Extra information about what caused gl_get_line() to return is available both by inspecting errno, and by calling the gl_return_status() function.GlReturnStatus gl_return_status(GetLine *gl);
GLR_NEWLINE - The last call to gl_get_line()
successfully returned a completed
input line.
GLR_BLOCKED - gl_get_line() was in non-blocking
server mode, and returned early to
avoid blocking the process while
waiting for terminal I/O. The
gl_pending_io() function can be
used to see what type of I/O
gl_get_line() was waiting for.
(see the gl_io_mode(3) man page
for details).
GLR_SIGNAL - A signal was caught by
gl_get_line() that had an
after-signal disposition of
GLS_ABORT (See gl_trap_signal()).
GLR_TIMEOUT - The inactivity timer expired while
gl_get_line() was waiting for
input, and the timeout callback
function returned GLTO_ABORT.
See gl_inactivity_timeout() for
information about timeouts.
GLR_FDABORT - An application I/O callack returned
GLFD_ABORT (see gl_watch_fd()).
GLR_EOF - End of file reached. This can happen
when input is coming from a file or a
pipe, instead of the terminal. It also
occurs if the user invokes the
list-or-eof or del-char-or-list-or-eof
actions at the start of a new line.
GLR_ERROR - An unexpected error caused
gl_get_line() to abort (consult
errno and/or
gl_error_message() for details.
const char *gl_error_message(GetLine *gl, char *buff,
size_t n);
OPTIONAL PROMPT FORMATTING¶
Whereas by default the prompt string that you specify is displayed literally, without any special interpretation of the characters within it, the gl_prompt_style() function can be used to enable optional formatting directives within the prompt.void gl_prompt_style(GetLine *gl, GlPromptStyle style);
GL_FORMAT_PROMPT - In this style, the formatting
directives described below, when
included in prompt strings, are
interpreted as follows:
%B - Display subsequent
characters with a bold
font.
%b - Stop displaying characters
with the bold font.
%F - Make subsequent characters
flash.
%f - Turn off flashing
characters.
%U - Underline subsequent
characters.
%u - Stop underlining
characters.
%P - Switch to a pale (half
brightness) font.
%p - Stop using the pale font.
%S - Highlight subsequent
characters (also known as
standout mode).
%s - Stop highlighting
characters.
%V - Turn on reverse video.
%v - Turn off reverse video.
%% - Display a single %
character.
For example, in this mode, a prompt
string like "%UOK%u$ " would
display the prompt "OK$ ",
but with the OK part
underlined.
Note that although a pair of
characters that starts with a %
character, but doesn't match any of
the above directives is displayed
literally, if a new directive is
subsequently introduced which does
match, the displayed prompt will
change, so it is better to always
use %% to display a literal %.
Also note that not all terminals
support all of these text
attributes, and that some substitute
a different attribute for missing
ones.
GL_LITERAL_PROMPT - In this style, the prompt string is
printed literally. This is the
default style.
ALTERNATE CONFIGURATION SOURCES¶
As mentioned above, by default users have the option of configuring the behavior of gl_get_line() via a configuration file called .teclarc in their home directories. The fact that all applications share this same configuration file is both an advantage and a disadvantage. In most cases it is an advantage, since it encourages uniformity, and frees the user from having to configure each application separately. In some applications, however, this single means of configuration is a problem. This is particularly true of embedded software, where there's no filesystem to read a configuration file from, and also in applications where a radically different choice of keybindings is needed to emulate a legacy keyboard interface. To cater for such cases, the following function allows the application to control where configuration information is read from. int gl_configure_getline(GetLine *gl,
const char *app_string,
const char *app_file,
const char *user_file);
gl_configure_getline(gl, "edit-mode vi \n nobeep",
"/usr/share/myapp/teclarc",
"~/.teclarc");
int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin,
const char *keyseq,
const char *action);
GL_USER_KEY - The user requested this key-binding.
GL_APP_KEY - This is a default binding set by the
application.
CUSTOMIZED WORD COMPLETION¶
If in your application, you would like to have TAB completion complete other things in addition to or instead of filenames, you can arrange this by registering an alternate completion callback function, via a call to the gl_customize_completion() function. int gl_customize_completion(GetLine *gl, void *data,
CplMatchFn *match_fn);
ADDING COMPLETION ACTIONS¶
In the previous section the ability to customize the behavior of the only default completion action, complete-word, was described. In this section the ability to install additional action functions, so that different types of word completion can be bound to different key-sequences, is described. This is achieved by using the gl_completion_action() function. int gl_completion_action(GetLine *gl,
void *data, CplMatchFn *match_fn,
int list_only, const char *name,
const char *keyseq);
DEFINING CUSTOM ACTIONS¶
Although the built-in key-binding actions are sufficient for the needs of most applications, occasionally a specialized application may need to define one or more custom actions, bound to application-specific key-sequences. For example, a sales application would benefit from having a key-sequence that displayed the part name that corresponded to a part number preceding the cursor. Such a feature is clearly beyond the scope of the built-in action functions. So for such special cases, the gl_register_action() function is provided.int gl_register_action(GetLine *gl, void *data, GlActionFn *fn, const char *name, const char *keyseq);
#define GL_ACTION_FN(fn) GlAfterAction (fn)(GetLine *gl, \
void *data, int count, size_t curpos, \
const char *line)
static GL_ACTION_FN(say_hello_fn)
{
if(gl_normal_io(gl)) /* Temporarily suspend editing */
return GLA_ABORT;
printf("Hello world\n");
return GLA_CONTINUE;
}
GLA_ABORT - Cause gl_get_line() to return NULL.
GLA_RETURN - Cause gl_get_line() to return the
completed input line.
GLA_CONTINUE - Resume command-line editing.
HISTORY FILES¶
To save the contents of the history buffer before quitting your application, and subsequently restore them when you next start the application, the following functions are provided. int gl_save_history(GetLine *gl, const char *filename,
const char *comment, int max_lines);
int gl_load_history(GetLine *gl, const char *filename,
const char *comment);
MULTIPLE HISTORY LISTS¶
If your application uses a single GetLine object for entering many different types of input lines, you may wish gl_get_line() to distinguish the different types of lines in the history list, and only recall lines that match the current type of line. To support this requirement, gl_get_line() marks lines being recorded in the history list with an integer identifier chosen by the application. Initially this identifier is set to 0 by new_GetLine(), but it can be changed subsequently by calling gl_group_history().int gl_group_history(GetLine *gl, unsigned id);
DISPLAYING HISTORY¶
The history list can be displayed by calling gl_show_history(). int gl_show_history(GetLine *gl, FILE *fp,
const char *fmt,
int all_groups,
int max_lines);
%D - The date on which the line was originally
entered, formatted like 2001-11-20.
%T - The time of day when the line was entered,
formatted like 23:59:59.
%N - The sequential entry number of the line in
the history buffer.
%G - The number of the history group which the
line belongs to.
%% - A literal % character.
%H - The history line itself.
2001-11-20 10:23:34 Hello world
LOOKING UP HISTORY¶
The gl_lookup_history() function allows the calling application to look up lines in the history list. typedef struct {
const char *line; /* The requested historical */
/* line. */
unsigned group; /* The history group to which */
/* the line belongs. */
time_t timestamp; /* The date and time at which */
/* the line was originally */
/* entered. */
} GlHistoryLine;
int gl_lookup_history(GetLine *gl, unsigned long id,
GlHistoryLine *hline);
MANUAL HISTORY ARCHIVAL¶
By default, whenever a line is entered by the user, it is automatically appended to the history list, just before gl_get_line() returns the line to the caller. This is convenient for the majority of applications, but there are also applications that need finer grained control over what gets added to the history list. In such cases, the automatic addition of entered lines to the history list can be turned off by calling the gl_automatic_history() function.int gl_automatic_history(GetLine *gl, int enable);
int gl_append_history(GetLine *gl, const char *line);
EINVAL - One of the arguments passed to
gl_append_history() was NULL.
ENOMEM - The specified line was longer than the allocated
size of the history buffer (as specified when
new_GetLine() was called), so it couldn't be
archived.
MISCELLANEOUS HISTORY CONFIGURATION¶
If you wish to change the size of the history buffer that was originally specified in the call to new_GetLine(), you can do so with the gl_resize_history() function.int gl_resize_history(GetLine *gl, size_t histlen);
void gl_limit_history(GetLine *gl, int max_lines);
void gl_clear_history(GetLine *gl, int all_groups);
void gl_toggle_history(GetLine *gl, int enable);
QUERYING HISTORY INFORMATION¶
The configured state of the history list can be queried with the gl_history_state() function. typedef struct {
int enabled; /* True if history is enabled */
unsigned group; /* The current history group */
int max_lines; /* The current upper limit on the */
/* number of lines in the history */
/* list, or -1 if unlimited. */
} GlHistoryState;
void gl_state_of_history(GetLine *gl,
GlHistoryState *state);
typedef struct {
unsigned long oldest; /* The sequential entry number */
/* of the oldest line in the */
/* history list. */
unsigned long newest; /* The sequential entry number */
/* of the newest line in the */
/* history list. */
int nlines; /* The number of lines in the */
/* history list. */
} GlHistoryRange;
void gl_range_of_history(GetLine *gl, GlHistoryRange *range);
typedef struct {
size_t size; /* The size of the history buffer */
/* (bytes). */
size_t used; /* The number of bytes of the */
/* history buffer that are */
/* currently occupied. */
} GlHistorySize;
void gl_size_of_history(GetLine *gl, GlHistorySize *size);
CHANGING TERMINALS¶
The new_GetLine() constructor function assumes that input is to be read from stdin, and output written to stdout. The following function allows you to switch to different input and output streams. int gl_change_terminal(GetLine *gl, FILE *input_fp,
FILE *output_fp, const char *term);
EXTERNAL EVENT HANDLING¶
By default, gl_get_line() doesn't return until either a complete input line has been entered by the user, or an error occurs. In programs that need to watch for I/O from other sources than the terminal, there are two options. 1. Use the functions described in the
gl_io_mode(3) man page to switch
gl_get_line() into non-blocking server mode. In this mode,
gl_get_line() becomes a non-blocking, incremental
line-editing function that can safely be called from
an external event loop. Although this is a very
versatile method, it involves taking on some
responsibilities that are normally performed behind
the scenes by gl_get_line().
2. While gl_get_line() is waiting for keyboard
input from the user, you can ask it to also watch for
activity on arbitrary file descriptors, such as
network sockets, pipes etc, and have it call functions
of your choosing when activity is seen. This works on
any system that has the select() system call,
which is most, if not all flavors of unix.
int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
GlFdEventFn *callback, void *data);
GLFD_READ - Watch for the arrival of data to be read.
GLFD_WRITE - Watch for the ability to write to the file
descriptor without blocking.
GLFD_URGENT - Watch for the arrival of urgent
out-of-band data on the file descriptor.
#define GL_FD_EVENT_FN(fn) GlFdStatus (fn)(GetLine *gl, \
void *data, int fd, \
GlFdEvent event)
GLFD_ABORT - Tell gl_get_line() to abort. When this
happens, gl_get_line() returns
NULL, and a following call to
gl_return_status() will return
GLR_FDABORT. Note that if the
application needs errno always to
have a meaningful value when
gl_get_line() returns NULL,
the callback function should set
errno appropriately.
GLFD_REFRESH - Redraw the input line then continue
waiting for input. Return this if
your callback wrote to the terminal.
GLFD_CONTINUE - Continue to wait for input, without
redrawing the line.
SETTING AN INACTIVITY TIMEOUT¶
On systems with the select() system call, the gl_inactivity_timeout() function can be used to set or cancel an inactivity timeout. Inactivity in this case refers both to keyboard input, and to I/O on any file descriptors registered by prior and subsequent calls to gl_watch_fd(). On oddball systems that don't have select(), this call has no effect. int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *callback,
void *data, unsigned long sec,
unsigned long nsec);
#define GL_TIMEOUT_FN(fn) \
GlAfterTimeout (fn)(GetLine *gl, void *data)
GLTO_ABORT - Tell gl_get_line() to abort. When
this happens, gl_get_line() will
return NULL, and a following call
to gl_return_status() will return
GLR_TIMEOUT. Note that if the
application needs errno always to
have a meaningful value when
gl_get_line() returns NULL,
the callback function should set
errno appropriately.
GLTO_REFRESH - Redraw the input line, then continue
waiting for input. You should return
this value if your callback wrote to the
terminal without having first called
gl_normal_io(gl).
GLTO_CONTINUE - In normal blocking-I/O mode, continue to
wait for input, without redrawing the
user's input line.
In non-blocking server I/O mode (see
gl_io_mode(3)), cause gl_get_line()
to act as though I/O blocked. This means
that gl_get_line() will immediately
return NULL, and a following call
to gl_return_status() will return
GLR_BLOCKED.
SIGNAL HANDLING DEFAULTS¶
By default, the gl_get_line() function intercepts a number of signals. This is particularly important for signals which would by default terminate the process, since the terminal needs to be restored to a usable state before this happens. In this section, the signals that are trapped by default, and how gl_get_line() responds to them, is described. Changing these defaults is the topic of the following section. SIGINT - This signal is generated both by the keyboard
interrupt key (usually ^C), and the keyboard
break key.
errno=EINTR
SIGHUP - This signal is generated when the controlling
terminal exits.
errno=ENOTTY
SIGPIPE - This signal is generated when a program attempts
to write to a pipe who's remote end isn't being
read by any process. This can happen for example
if you have called gl_change_terminal() to
redirect output to a pipe hidden under a pseudo
terminal.
errno=EPIPE
SIGQUIT - This signal is generated by the keyboard quit
key (usually ^\).
errno=EINTR
SIGABRT - This signal is generated by the standard C,
abort() function. By default it both
terminates the process and generates a core
dump.
errno=EINTR
SIGTERM - This is the default signal that the UN*X
kill command sends to processes.
errno=EINTR
int gl_last_signal(const GetLine *gl);
SIGCONT - This signal is generated when a suspended
process is resumed.
SIGPOLL - On SVR4 systems, this signal notifies the
process of an asynchronous I/O event. Note
that under 4.3+BSD, SIGIO and SIGPOLL are
the same. On other systems, SIGIO is ignored
by default, so gl_get_line() doesn't
trap it by default.
SIGPWR - This signal is generated when a power failure
occurs (presumably when the system is on a
UPS).
SIGALRM - This signal is generated when a timer
expires.
SIGUSR1 - An application specific signal.
SIGUSR2 - Another application specific signal.
SIGVTALRM - This signal is generated when a virtual
timer expires (see man setitimer(2)).
SIGXCPU - This signal is generated when a process
exceeds its soft CPU time limit.
SIGXFSZ - This signal is generated when a process
exceeds its soft file-size limit.
SIGTSTP - This signal is generated by the terminal
suspend key, which is usually ^Z, or the
delayed terminal suspend key, which is
usually ^Y.
SIGTTIN - This signal is generated if the program
attempts to read from the terminal while the
program is running in the background.
SIGTTOU - This signal is generated if the program
attempts to write to the terminal while the
program is running in the background.
CUSTOMIZED SIGNAL HANDLING¶
The previous section listed the signals that gl_get_line() traps by default, and described how it responds to them. This section describes how to both add and remove signals from the list of trapped signals, and how to specify how gl_get_line() should respond to a given signal.int gl_ignore_signal(GetLine *gl, int signo);
int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
GlAfterSignal after, int errno_value);
GLS_RESTORE_SIG - Restore the caller's signal
environment while handling the
signal.
GLS_RESTORE_TTY - Restore the caller's terminal settings
while handling the signal.
GLS_RESTORE_LINE - Move the cursor to the start of the
line following the input line before
invoking the application's signal
handler.
GLS_REDRAW_LINE - Redraw the input line when the
application's signal handler returns.
GLS_UNBLOCK_SIG - Normally, if the calling program has
a signal blocked (man sigprocmask),
gl_get_line() does not trap that
signal. This flag tells gl_get_line()
to trap the signal and unblock it for
the duration of the call to
gl_get_line().
GLS_DONT_FORWARD - If this flag is included, the signal
will not be forwarded to the signal
handler of the calling program.
GLS_RESTORE_ENV = GLS_RESTORE_SIG | GLS_RESTORE_TTY |
GLS_REDRAW_LINE
GLS_SUSPEND_INPUT = GLS_RESTORE_ENV | GLS_RESTORE_LINE
1. The cursor doesn't get left in the middle of the input
line.
2. So that the user can type in input and have it echoed.
3. So that you don't need to end each output line with
\r\n, instead of just \n.
GLS_RETURN - Return the completed input line, just as
though the user had pressed the return
key.
GLS_ABORT - Cause gl_get_line() to abort. When
this happens, gl_get_line() returns
NULL, and a following call to
gl_return_status() will return
GLR_SIGNAL. Note that if the
application needs errno always to
have a meaningful value when
gl_get_line() returns NULL,
the callback function should set
errno appropriately.
GLS_CONTINUE - Resume command line editing.
RELIABLE SIGNAL HANDLING¶
Signal handling is suprisingly hard to do reliably without race conditions. In gl_get_line() a lot of care has been taken to allow applications to perform reliable signal handling around gl_get_line(). This section explains how to make use of this.configure gl_get_line() to abort when important
signals are caught.
signals that it catches are blocked when
gl_get_line() is called, they will be unblocked
automatically during times when gl_get_line() is
waiting for I/O. This can be done either
on a per signal basis, by calling the
gl_trap_signal() function, and specifying the
GLS_UNBLOCK attribute of the signal, or globally by
calling the gl_catch_blocked() function.
void gl_catch_blocked(GetLine *gl);
This function simply adds the GLS_UNBLOCK attribute
to all of the signals that it is currently configured to
trap.
of all of the signals that gl_get_line() is
configured to trap. This can be done using the POSIX
sigprocmask() function in conjunction with the
gl_list_signals() function.
int gl_list_signals(GetLine *gl, sigset_t *set);
This function returns the set of signals that it is
currently configured to catch in the set argument,
which is in the form required by sigprocmask().
the signal handler sets, knowing that there is now no
danger of this flag being set again until
gl_get_line() unblocks its signals while performing
I/O.
a signal was caught, an error occurred, or the user
finished entering their input line.
it is set, respond to it, and zero the flag.
blocked in step 3.
a. It uses the POSIX sigaction() function to register
a temporary signal handler to all of the signals that it
is configured to catch. This signal handler does two
things.
1. It records the number of the signal that was received
in a file-scope variable.
2. It then calls the POSIX siglongjmp()
function using the buffer that was passed to
sigsetjmp() for its first argument, and
a non-zero value for its second argument.
When this signal handler is registered, the sa_mask
member of the struct sigaction act argument of the
call to sigaction() is configured to contain all of
the signals that gl_get_line() is catching. This
ensures that only one signal will be caught at once by
our signal handler, which in turn ensures that multiple
instances of our signal handler don't tread on each
other's toes.
b. Now that the signal handler has been set up,
gl_get_line() unblocks all of the signals that it
is configured to catch.
c. It then calls the read() or select() system
calls to wait for keyboard input.
d. If this system call returns (ie. no signal is received),
gl_get_line() blocks delivery of the signals of
interest again.
e. It then reinstates the signal handlers that were
displaced by the one that was just installed.
attributes of the signal that was caught,
gl_get_line() restores the terminal attributes to
the state that they had when gl_get_line() was
called. This is particularly important for signals that
suspend or terminate the process, since otherwise the
terminal would be left in an unusable state.
function to re-send the application the signal that
was caught.
sent. This results in the signal that was just sent
via raise(), being caught by the application's
original signal handler, which can now handle it as it
sees fit.
the process), gl_get_line() blocks delivery of the
above signal again.
above steps, and redisplays the line, if the signal
configuration calls for this.
read a character, or aborts, depending on the
configuration of the signal that was caught.
THE TERMINAL SIZE¶
On most systems the combination of the TIOCGWINSZ ioctl and the SIGWINCH signal is used to maintain an accurate idea of the terminal size. The terminal size is newly queried every time that gl_get_line() is called and whenever a SIGWINCH signal is received.int gl_set_term_size(GetLine *gl, int ncolumn, int nline);
typedef struct {
int nline; /* The terminal has nline lines */
int ncolumn; /* The terminal has ncolumn columns */
} GlTerminalSize;
GlTerminalSize gl_terminal_size(GetLine *gl,
int def_ncolumn,
int def_nline);
HIDING WHAT YOU TYPE¶
When entering sensitive information, such as passwords, it is best not to have the text that you are entering echoed on the terminal. Furthermore, such text should not be recorded in the history list, since somebody finding your terminal unattended could then recall it, or somebody snooping through your directories could see it in your history file. With this in mind, the gl_echo_mode() function allows you to toggle on and off the display and archival of any text that is subsequently entered in calls to gl_get_line().int gl_echo_mode(GetLine *gl, int enable);
SINGLE CHARACTER QUERIES¶
Using gl_get_line() to query the user for a single character reply, is inconvenient for the user, since they must hit the enter or return key before the character that they typed is returned to the program. Thus the gl_query_char() function has been provided for single character queries like this. int gl_query_char(GetLine *gl, const char *prompt,
char defchar);
READING RAW CHARACTERS¶
Whereas the gl_query_char() function visibly prompts the user for a character, and displays what they typed, the gl_read_char() function reads a signal character from the user, without writing anything to the terminal, or perturbing any incompletely entered input line. This means that it can be called not only from between calls to gl_get_line(), but also from callback functions that the application has registered to be called by gl_get_line().int gl_read_char(GetLine *gl);
CLEARING THE TERMINAL¶
The calling program can clear the terminal by calling gl_erase_terminal(). In non-blocking server-I/O mode, this function also arranges for the current input line to be redrawn from scratch when gl_get_line() is next called.int gl_erase_terminal(GetLine *gl);
DISPLAYING TEXT DYNAMICALLY¶
Between calls to gl_get_line(), the gl_display_text() function provides a convenient way to display paragraphs of text, left-justified and split over one or more terminal lines according to the constraints of the current width of the terminal. Examples of the use of this function may be found in the demo programs, where it is used to display introductions. In those examples the advanced use of optional prefixes, suffixes and filled lines to draw a box around the text is also illustrated. int gl_display_text(GetLine *gl, int indentation,
const char *prefix,
const char *suffix, int fill_char,
int def_width, int start,
const char *string);
CALLBACK FUNCTION FACILITIES¶
Unless otherwise stated, callback functions, such as tab completion callbacks and event callbacks should not call any functions in this module. The following functions, however, are designed specifically to be used by callback functions.void gl_replace_prompt(GetLine *gl, const char *prompt);
INTERNATIONAL CHARACTER SETS¶
Since libtecla version 1.4.0, gl_get_line() has been 8-bit clean. This means that all 8-bit characters that are printable in the user's current locale are now displayed verbatim and included in the returned input line. Assuming that the calling program correctly contains a call like the following,setlocale(LC_CTYPE, "");
locale -a
THREAD SAFETY¶
In a multi-threaded program, you should use the libtecla_r.a version of the library. This uses reentrant versions of system functions, where available. Unfortunately neither terminfo nor termcap were designed to be reentrant, so you can't safely use the functions of the getline module in multiple threads (you can use the separate file-expansion and word-completion modules in multiple threads, see the corresponding man pages for details). However due to the use of POSIX reentrant functions for looking up home directories etc, it is safe to use this module from a single thread of a multi-threaded program, provided that your other threads don't use any termcap or terminfo functions.FILES¶
libtecla.a - The tecla library libtecla.h - The tecla header file. ~/.teclarc - The personal tecla customization file.
SEE ALSO¶
libtecla(3), gl_io_mode(3), tecla(7), ef_expand_file(3), cpl_complete_word(3), pca_lookup_file(3)