Input Interaction (XForms (Forms Library) - Version 1.2 (Rev. 4) A Graphical User Interface Toolkit for X)

Next: Other Input Routines, Previous: Input Types, Up: Part III Input Objects [Contents][Index]

### 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 into 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

  `<Backspace>`, `<Ctrl>h`

delete next char

  `<Delete>`

delete previous word

  `<Ctrl><Backspace>`

delete next word

  `<Ctrl><Delete>`

delete from cursor position to end of line

  `<Ctrl>k`

delete from cursor position to begin of line

  `<Meta>h`

jump to begin of line

  `<Ctrl>a`

jump to end of line

  `<Ctrl>e`

move char backward

  `<Ctrl>b`

move char forward

  `<Ctrl>f`

move to next line

  `<Ctrl>n`, `<Down>`

move to previous line

  `<Ctrl>p`, `<Up>`

move word backward

  `<Meta>b`

move word forward

  `<Meta>f`

move to begin of field

  `<Home>`

move to end of field

  `<End>`

clear input field

  `<Ctrl>u`

paste

  `<Ctrl>y`

It is possible to remap the the bindings, see below for details.

A single click into the input field positions the cursor at the position of the mouse click.

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>` or `<Delete>` key or replaced by what the user types in.

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 input 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 become invoked), the `fl_set_object_return()` function can be used with one of the following values:

`FL_RETURN_NONE`

  Never return or invoke callback

`FL_RETURN_END_CHANGED`

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

`FL_RETURN_CHANGED`

  Return or invoke the callback function whenever the field had been 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.

A few additional notes: when you read "the fields has been changed" this includes the case that the user e.g., deleted a character and then added it back again. Also this case is reported as a "change" (a delete alone isn’t) so the term "changed" does not necessarily mean that the content of the field has changed but that the user made changes (but which still might result in the exact same content as before).

Another term that may be understood differently is "end". In the versions since 1.0.91 it means that the users either hits the `<Tab>` or the `<Return>` key (except for multi-line inputs) or that she clicks onto some other object that in principle allows user interaction. These events are interpreted as an indication the user is done editing the input field and thus are reported back to the program, either by returning the input object or invoking its callback. But unless the user goes to a different input object the input field edited retains the focus.

Up to version 1.0.90 this was handled a bit differently: an "end of edit" event was not reported back to the program when the user clicked on a non-input object, i.e., changed to a different input object. This let to some problems when the interaction with the clicked-on non-input object dependet on the new content of the input object, just having been edited, but which hadn’t been been reported back to the caller. On the other hand, some programs rely on the "old" behaviour. These programs can switch back to the traditional behaviour by calling the new function (available since 1.0.93)

    fl_input_end_return_handling(int type);

where `type` can be either `FL_INPUT_END_EVENT_ALWAYS`, which is now the default, or `FL_INPUT_END_EVENT_CLASSIC`, which switches back to the type of handing used in versions up and including to 1.0.90. The function can be used at any time to change between the two possible types of behaviour. The function returns the previous setting.

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 unlimited, set `maxchars` to 0. Note that input objects of type `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 method may simplify this task considerably:

    typedef int (*FL_INPUT_VALIDATOR)(FL_OBJECT *obj, const char *old,
                                     const char *cur, int c);
    FL_INPUT_VALIDATOR fl_set_input_filter(FL_OBJECT *obj,
                                           FL_INPUT_VALIDATOR 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 doesn’t happpen if a custom 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 against such cases 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 is `FL_INVALID | FL_RINGBELL` the keyboard bell is sound, the object is also 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(obj, 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`.

There are two slightly different input modes for input objects. In the "normal" mode, when the input field is entered not using the mouse (e.g., by using of the <Tab> key) the cursor is placed again at the position it was when the field was left (or at the end of a possibly existing string when it’s entered for the first time). When an input object has a maximum number of allowed characters set (via the `fl_set_input_maxchars()` function) and there’s no room left no new input is accepted until at least one character has been deleted.

As an alternative there’s an input mode that is similar to the way things were handle in DOS forms etc. Here, when the field is entered by any means but clicking into it with the mouse, the cursor is placed at the start of the text. And for fields with a maximum capacity, that contain already as many characters as possible, the character at the end of the field are removed when a new one is entered.

To switch between the two modes use the function

where `mode` is one of

`FL_NORMAL_INPUT_MODE`

  The default. Use it to switch to the "normal" input mode

`FL_DOS_INPUT_MODE`

  For selecting the DOS-like input mode (in this mode, when a maximum number of characters has been set, as many characters already have been entered, and a new character is inserted somewhere in the middle the character at the very end gets deleted to make room for the new character)

The function returns the previous setting. Note that the function changes the input mode for all input fields in your application.

Next: Other Input Routines, Previous: Input Types, Up: Part III Input Objects [Contents][Index]