[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

18. Input Objects

It is often required to obtain textual input from the user, e.g. a file name, some fields in a database, etc. To this end input fields exist in the Forms Library. An input field is a field that can be edited by the user using the keyboard.


18.1 Adding Input Objects

Adding an object To add an input field to a form you use the routine

 
FL_OBJECT *fl_add_input(int type, FL_Coord x, FL_Coord y,
                        FL_Coord w, FL_Coord h, const char *label)

The meaning of the parameters is as usual. The label is by default placed in front of the input field.


18.2 Input Types

The following types of input fields exist:

FL_NORMAL_INPUT

Any type of text can be typed into this field.

FL_FLOAT_INPUT

Only a float value can be typed in (e.g. -23.2e12).

FL_INT_INPUT

Only an integer value can be typed in (e.g. -86).

FL_DATE_INPUT

Only a date (MM/DD/YY or DD/MM/YY) can be typed in (and limited per default to 10 characters).

FL_MULTILINE_INPUT

An input field allowing for multiple lines.

FL_SECRET_INPUT

A normal input field that does not show the text (and limited per default to a maximum length of 16 characters).

FL_HIDDEN_INPUT

A normal input field but invisible.

A normal input field can contain one line of text, to be typed in by the user. A float input field can only contain a float number. If the user tries to type in something else than a float, it is not shown and the bell is sounded. Similarly, an int input field can only contain an integer number and a date input field can only contain a valid date (see below). A multi-line input field can contain multiple lines of text. A secret input field works like a normal input field but the text is not shown (or scrambled). Only the cursor is shown which does move while text is being entered. This can for example be used for getting passwords. Finally, a hidden input field is not shown at all but does collect text for the application program to use.


18.3 Input Interaction

Whenever the user presses the mouse inside an input field a cursor will appear in it (and the field will change color to indicate that it received the input focus). Further input will be directed to this field. The user can use the following keys (as in emacs(1)) to edit or move around inside the input field:

delete previous char

<DELETE>

delete next char

<Ctrl>D

delete previous word

<Meta><Delete>, <Ctrl>W

delete next word

<Meta>d

delete to end of line

<Ctrl>k

backspace

<Ctrl>H

jump to beginning of line

<Ctrl>A, <Shift><Left>

jump to end of line

<Ctrl>E, <Shift><Right>

move char backward

<Ctrl>B, <Left>

move char forward

<Ctrl>F, <Right>

move to next line

<Ctrl>N, <Down>

move to previous line

<Ctrl>P, <Up>

move to next page

<PageDown>

nove to previous page

<PageUp>

move word backward

<Meta>b

move word forward

<Meta>f

move to begin of field

<Meta>!, <HOME>, <SHIFT><UP>

move to end of field

<Meta>?, <Ebd>, <Shift><Dwon>

clear input field

<Ctrl>U

paste

<Ctrl>y

It is possible to remap the the bindings, see later for details. There are three ways to select part of the input field. Dragging, double-click and triple-click. A double-click selects the word the mouse is on and a triple-click selects the entire line the mouse is on. The selected part of the input field is removed when the user types the <Backspace> key or replaced by what the user types in. Also the cursor can be placed at different positions in the input field using the mouse.

One additional property of selecting part of the text field is that if the selection is done with the left mouse button the selected part becomes the primary (XA PRIMARY) selection of the X Selection mechanism, thus other applications, e.g., xterm, can request this selection. Conversely, the cut-buffers from other applications can be pasted into the input field. Use the middle mouse button for pasting. Note that <Ctrl>y only pastes the cut-buffer generated by <Ctrl>k and is not related to the X Selection mechanism, thus it only works within the same application. When the user presses the <Tab> key the input field is returned to the application program and the input focus is directed to the next input field. This also happens when the user presses the <Return> key but only if the form does not contain a return button. The order which input fields get the focus when the <Tab> is pressed is the same as the order the input fields were added to the form. From within Form Designer, using the raising function you can arrange (re-arrange) the focus order, see Raising and Lowering, in Part II for details. If the <Shift> key is pressed down when the <Tab> is pressed, the focus is directed to the previous input field.

Leaving an inut field using the <Return>) key does not work for multi-line input fields since the <Return> key is used to start a new line.

Per default the input object gets returned to the application (or the callback set for the input object is invoked) when the input field is left and has been changed. Depending on the application, other options might be useful. To change the precise condition for the object to be returned (or its callback to becone invoked), the following function can be used:

 
void fl_set_input_return(FL_OBJECT *obj, int when);

Where when can take one of the following values:

FL_RETURN_END_NONE

Never return or invoke callback

FL_RETURN_END_CHANGED

Default, object is returned or callback is called at the end if the field is modified.

FL_RETURN_CHANGED

Return or invoke the callback function whenever the field is changed.

FL_RETURN_END

Return or invoke the callback function at the end regardless if the field was modified or not.

FL_RETURN_ALWAYS

Return or invoke the callback function upon each keystroke and at the end (regardless if the field was changed or not)

See demo `objreturn.c' for an example use of this.

There is a routine that can be used to limit the number of characters per line for input fields of type FL_NORMAL_INPUT

 
void fl_set_input_maxchars(FL_OBJECT *obj, int maxchars);

To reset the limit to infinite, set maxchars to 0. Note that input objects of types FL_DATE_INPUT are limited to 10 characters per default and those of type FL_SECRET_INPUT to 16.

Although an input of type FL_RETURN_ALWAYS can be used in combination with the callback function to check the validity of characters that are entered into the input field, use of the following is typically more appropriate

 
typedef int (*FL_INPUTVALIDATOR)(FL_OBJECT *obj, const char *old,
                                 const char *cur, int c);
FL_INPUTVALIDATOR fl_set_input_filter(FL_OBJECT *obj,
                                      FL_INPUTVALIDATOR filter);

The function filter is called whenever a new (regular) character is entered. old is the string in the input field before the newly typed character c was added to form the new string cur. If the new character is not an acceptable character for the input field, the filter function should return FL_INVALID otherwise FL_VALID. If FL_INVALID is returned, the new character is discarded and the input field remains unmodified. The function returns the old filter. While the built-in filters also sound the keyboard bell, this don't happpens if a custn filter only returns FL_INVALID. To also sound the keyboard bell logically or it with FL_INVALID | FL_RINGBELL.

This still leaves the possibility that the input is valid for every character entered, but the string is invalid for the field because it is incomplete. For example, 12.0e is valid for a float input field for every character typed, but the final string is not a valid floating point number. To guard again this, the filter function is also called just prior to returning the object with the argument c (for the newly entered character) set to zero. If the validator returns FL_INVALID the object is not returned to the application program, but input focus can change to the next input field. If the return value FL_INVALID | FL_RINGBELL, the keyboard bell is sound and the object is not returned to the application program and the input focus remains in the object.

To facilitate specialized input fields using validators, the following validator dependent routines are available

 
void fl_set_input_format(FL_OBJECT *obj, int attrib1, int attrib2);
void fl_get_input_format(FL_OBJECT *obj, int *attrib1, int *attrib2);

These two routines more or less provide a means for the validator to store and retrieve some information about user preference or other state dependent information. attrib1 and attrib2 can be any validator defined variables. For the built-in class, only the one of type FL_DATE_INPUT utilizes these to store the date format: for attrib1, it can take FL_INPUT_MMDD or FL_INPUT_DDMM and attrib2 is the separator between month and day. For example, to set the date format to dd/mm, use

 
fl_set_input_format(ob, FL_INPUT_DDMM,'/');

For the built-in type FL_DATE_INPUT the default is FL_INPUT_MMDD and the separator is '/'. There is no limit on the year other than it must be an integer and appear after month and day.

The function

 
int fl_validate_input( FL_OBJECT * obj);

can be used to test if the value in an input field is valid. It returns FL_VALID if the value is valid or if there is no validator function set for the input, otherwise FL_INVALID.


18.4 Other Input Routines

Note that the label is not the default text in the input field. To set the contents of the input field use the routine

 
void fl_set_input(FL_OBJECT *obj, const char *str);

There is very limited check for the validity of the string set for the input field. Use an empty string to clear an input field.

Setting the content of an input field does not trigger object event, i.e., the object callback is not called. In some situations you might want to have the callback invoked. For this, use the the function fl_call_object_callback()

 
void fl_call_object_callback(FL_OBJECT *obj);

To obtain the string in the field (when the user has changed it) use:

 
const char *fl_get_input(FL_OBJECT *obj);

This function returns a char pointer for all input types. Thus for numerical input types e.g. strtol(3), atoi(3), strtod(3), atof(3) or sscanf(3) should be used to convert the string to the proper data type you need. For multiline input, the returned pointer points to the entire content with possibly embedded newlines. The application may not modify the content pointed to by the returned pointer, it points to the internal buffer.

To select or deselect the current input or part of it, the following two routines can be used

 
void fl_set_input_selected(FL_OBJECT *obj, int flag);
void fl_set_input_selected_range(FL_OBJECT *obj, int start, int end);

where start and end are measured in characters. When start is 0 and end equals the number of characters in the string, fl_set_input_selected() makes the entire input field selected. However, there is a subtle difference between this routine and fl_set_input_selected() when called with flag set to 1: fl_set_input_selected() always places the cursor at the end of the string while fl_set_input_selected_range()q places the cursor at the beginning of the selection.

To obtain the currently selected range, either selected by the application or by the user, use the following routine

 
const char *fl_get_input_selected_range(FL_OBJECT *obj,
                                        int *start, int *end);

where start and end, if not NULL, are set to the begining and end position of the selected range, measured in characters. For example, if start is 5 after the function returned and end is 7, it means the selection starts at character 6 (str[5]) and ends before character 8 (str[7]), so a total of two characters are selected (i.e., character 6 and 7). The function returns the selected string (which may not be modified). If there is currently no selection, the function returns NULL and both start and end are set to -1. Note that the char pointer returned by the function points to (kind of) a static buffer, and will be overwritten by the next call.

It is possible to obtain the cursor position using the following routine

 
int fl_get_input_cursorpos(FL_OBJECT *obj, int *xpos, int *ypos);

The function returns the cursor position measured in number of characters (including newline characters) in front of the cursor. If the input field does not have input focus (thus does not have a cursor), the function returns -1. Upon function return, ypos is set to the number of the line (starting from 1) the cursor is on, and xpos set to the number of characters in front of the cursor measured from the beginning of the current line as indicated by ypos. If the input field does not have input focus the xpos is set to -1.

It is possible to move the cursor within the input field programmatically using the following routine

 
void fl_set_input_cursorpos(FL_OBJECT *obj, int xpos, int ypos);

where xpos and ypos are measured in characters (lines). E.g., given the input field "an arbitrary string" the call

 
fl_set_input_cursorpos(ob, 4, 1);

places the the cursor after the first character of the word "arbitrary", i.e. directly after the first a.

Shortcut keys can be associated with an input field to switch input focus. To this end, use the following routine

 
void fl_set_input_shortcut(FL_OBJECT *obj, const char *sc,
                           int showit);

By default, if an input field of type FL_MULTILINE_INPUT contains more text than can be shown, scrollbars will appear with which the user can scroll the text around horizontally or vertically. To change this default, use the following routines

 
void fl_set_input_hscrollbar(FL_OBJECT *obj, int how);
void fl_set_input_vscrollbar(FL_OBJECT *obj, int how);

where how can be one of the following values

FL_AUTO

The default. Shows the scrollbar only if needed.

FL_ON

Always shows the scrollbar.

FL_OFF

Never show scrollbar.

Note however that turning off scrollbars for an input field does not turn off scrolling, the user can still scroll the field using cursor and other keys.

To completely turn off scrolling for an input field (for both multiline and single line input field), use the following routine with a false value for yes_no

 
void fl_set_input_scroll(FL_OBJECT *obj, int yes_no);

There are also routines that can scroll the input field programmatically. To scroll vertically (for input fields of type FL_MULTILINE_INPUT only), use

 
void fl_set_input_topline(FL_OBJECT *obj, int line);

where line is the new top line (starting from 1) in the input field. To programmatically scroll horizontally, use the following routine

 
void fl_set_input_xoffset(FL_OBJECT *obj, int pixels);

where pixels, whoch must be a positive number, indicates how many pixels to scroll to the left relative to the nominal position of the text lines.

To obtain the current xoffset, use

 
int fl_get_input_xoffset(FL_OBJECT *obj);

It is possible to turn off the cursor of the input field using the following routine with a false value for yes_no:

 
void fl_set_input_cursor_visible(FL_OBJECT *obj, int yes_no);

To obtain the number of lines in the input field, call

 
int fl_get_input_numberoflines(FL_OBJECT *obj);

To obtain the current topline in the input field, use

 
int fl_get_input_topline(FL_OBJECT *obj);

To obtain the number of lines that fit inside the input box, use

 
int fl_get_input_screenlines(FL_OBJECT *obj);

For secret input field, the default is to draw the text using spaces. To change the character used to draw the text, the following function can be used

 
int fl_set_input_fieldchar(FL_OBJECT *obj, int field_char);

The function returns the old field char.


18.5 Input Attributes

Never use FL_NO_BOX as the boxtype.

The first color argument (col1) to fl_set_object_color() controls the color of the input field when it is not selected and the second (col2) is the color when selected.

To change the color of the input text or the cursor use

 
void fl_set_input_color(FL_OBJECT *obj, FL_COLOR tcol, FL_COLOR ccol);

Here tcol indicates the color of the text and ccol is the color of the cursor.

If you want to know the colors of the text and cursor use

 
void fl_get_input_color(FL_OBJECT *obj, FL_COLOR *tcol, FL_COLOR *ccol);

By default, the scrollbar size is dependent on the initial size of the input box. To change the size of the scrollbars, use the following routine

 
void fl_set_input_scrollbarsize(FL_OBJECT *obj, int hh, int vw);

where hh is the horizontal scrollbar height and vw is the vertical scrollbar width in pixels.

To determine the current settings for the orizontal scrollbar height and the vertical scrollbar width use

 
void fl_get_input_scrollbarsize(FL_OBJECT *obj, int *hh, int *vw);

The default scrollbar types are FL_HOR_THIN_SCROLLBAR and FL_VERT_THIN_SCROLLBAR. There are two ways you can change the default. One way is to use fl_set_defaults() or fl_set_scrollbar_type() to set the application wide default (preferred); another way is to use fl_get_object_component() to get the object handle to the scrollbars and change the the object type forcibly. Although the second method of changing the scrollbar type is not recommended, the object handle obtained can be useful in changing the scrollbar colors etc.

As mentioned earlier, it is possible for the application program to change the default edit keymaps. The editing key assignment is held in a structure of type FL_EditKeymap defined as follows:

 
typedef struct {
    long del_prev_char;     /* delete previous char */
    long del_next_char;     /* delete next char */
    long del_prev_word;     /* delete previous word */
    long del_next_word;     /* delete next word */
    long moveto_prev_line;  /* one line up */
    long moveto_next_line;  /* one line down */
    long moveto_prev_char;  /* one char left */
    long moveto_next_char;  /* one char right */
    long moveto_prev_word;  /* one word left */
    long moveto_next_word;  /* one word right */
    long moveto_prev_page;  /* one page up */
    long moveto_next_page;  /* one page down */
    long moveto_bol;        /* move to begining of line */
    long moveto_eol;        /* move to end of line */
    long moveto_bof;        /* move to begin of file */
    long moveto_eof;        /* move to end of file */
    long transpose;         /* switch two char positions*/
    long paste;             /* paste the edit buffer */
    long backspace;         /* alias for del_prev_char */
    long del_to_eol;        /* cut to end of line */
    long del_to_bol;        /* cut to end of line */
    long clear_field;       /* delete all */
    long del_to_eos;        /* not implemented yet */
} FL_EditKeymap;

To change the default edit keymaps, the following routine is available:

 
void fl_set_input_editkeymap(FL_EditKeymap *km);

with a filled or partially filled FL_EditKeymap structure. The unfilled members must be set to 0 so the default mapping is retained. Change of edit keymap is global and affects all input field within the application.

Calling fl_set_input_editkeymap() with km set to NULL restores the default. All cursor keys (<Left>, <Home> etc.) are reserved and their meanings hard-coded, thus can't be used in the mapping. For example, if you try to set del_prev_char to <Home>, pressing the <Home> key will not delete the previous character.

In filling the keymap structure, ASCII characters (i.e. characters with values below 128, including the control characters with values below 32) should be specified by their ASCII codes (<Ctrl> C is 3 etc.), while all others by their Keysyms (XK_F1 etc.). Control and special character combinations can be obtained by adding FL_CONTROL_MASK to the Keysym. To specify Meta add FL_ALT_MASK to the key value.

 
FL_EditKeymap ekm;
memset(ekm, 0, sizeof ekm);                   /* zero struct */
ekm.del_prev_char = 8;                        /* control-H */
ekm.del_next_char = 127;                      /* delete */
ekm.del_prev_word = 'h' | FL_ALT_MASK;        /* meta-H */
ekm.del_next_word = 127 | FL_ALT_MASK;        /* meta-delete */
ekm.moveto_bof    = XK_F1;                    /* F1 to bof */
ekm.moveto_eof    = XK_F1 | FL_CONTROL_MASK;  /* cntl-F1 to eof */

fl_set_input_editkeymap(&ekm);

18.6 Remarks

Always make sure that the input field is high enough to contain a single line of text. If the field is not high enough, the text may get clipped, i.e., become invisible.

See the program `demo06.c' for an example of the use of input fields. See `minput.c' for multi-line input fields. See `secretinput.c' for secret input fields and `inputall.c' for all input fields.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Build Daemon user on November 7, 2009 using texi2html 1.82.