The exact behaviour of the DP4 input functions as the user moves between fields in data entry maps is complex. (In menu maps the behaviour is straight forward - the field number is always immediately set to the user's intended field immediately.) The following explanation applies whether the inpm_x() or the older scrnx_map() functions are in use. First the big picture:
Whenever the user attempts to jump forwards in a dialog the intermediate fields are executed with jump TRUE. Calls to the inpm_x() functions just update the displayed values and return 0 indicating validation is needed, so if a field contains an invalid value, the program will trap the value, set jump FALSE and set the field number back to the field requiring correction, and data entry will continue normally from the problem field. It is impossible to reach a field without performing all the validations associated with the earlier fields.
If the user enters data in the normal way or the field was executed with jump TRUE the field number is set to the next input field, and abort_code to 0. If range is non zero then range is increased to the next field number if it is not already larger than this. (After the last field when field number is set to zero range is still increased as though there were another field. This is to avoid problems with repeated clearfirsting on the last input field)
Depending on the userdata.sys settings, and the context, pressing either the Enter or the Tab key may be considered to represent a request to complete the dialog. The variable jump is set to TRUE in this case to cause remaining entry fields to be skipped but validated. After the last field is processed field number is set to 0 to indicate the dialog has been completed. Clicking an OK button (a button mapped to the Enter key) is always treated as a request to complete the dialog, regardless of the effect that actually pressing Enter would have. If SAA or Windows behaviour is not selected Enter on the last field completes a dialog, even though it would not if there were another field. This is the reason for providing the ASK_CONFIRM flag in map_get_inputs(), and why it is not used when SAA or Windows behaviour is selected.
If the user uses the cursor left, cursor up or home keys to leave the field (or any input, including mouse, which means move to an earlier field) the field number is set to the requested field immediately.
If the user uses the cursor right,cursor down or end keys to leave the field (or any input which means move to a later field) the terminal manager discovers and remembers the field being aimed at, sets jump TRUE and returns a non zero value leaving the field number unchanged. Intervening fields are executed with jump TRUE. Assuming jump is not set FALSE explicitly by the program during the intervening processing, then after the field prior to the field being aimed at is executed jump is set FALSE once again. To the user it will appear that the cursor has jumped directly to the target field. If jump is set FALSE before the target is reached then the terminal manager forgets that a target was being aimed at and continues normally.
This scheme is complicated by the clearfirst variable. Setting clearfirst to 1 has two distinct effects:
It causes jump to be set FALSE at the start of a call to a field input function.
It causes the value in the field to be set to the default value for the field if the mapfield is a clearfirst field and range is zero or less than or equal to the current field number (indicating that this is the first time the user has reached this field)
The first of these effects would stop the method being described for navigating through entry fields working whenever clearfirst was set to TRUE. To get round this the terminal manager is forced to save and restore clearfirst, (it is saved at the time jump is set TRUE, and restored when it is set FALSE again: if the program sets jump FALSE, rather than the terminal manager it is restored at the next call to a field input function). However this first feature of clearfirst is in any case undesirable as it forces the user to enter a value into every field in the dialog. If clearfirst is required it should be set to 2: this has the same data defaulting effects of clearfirst = TRUE,but jump is unaffected (as for clearfirst = FALSE). Thus for clearfirst =2 the value of clearfirst is never changed by the terminal manager.
The explanation above is slightly inaccurate in one respect: if the user navigates away from a field and the target field is a button field, the terminal manager immediately activates the button, but without returning control to the calling program first. Control is only returned to the program when the user navigates away from the button to an "ordinary" field, and then the navigation is handled as though the user had navigated from the original input field. If the button is pressed, and it represents a "Special Key" control is returned to the program as though the user had navigated away from the original input field with that key. For example clicking on a Cancel button, will cause inpm_x() to return ESCAPE.
Your program may need to disable or skip over some of the entry fields some of the time. This is done by falling the inpm_omit() or inpm_ban() functions. These functions are designed to cope with the situation that arises when a field that is navigated to turns out not to be used for data entry. In this case the terminal manager selects a new target field and navigates to that in the same way as has already been described. How the field is chosen depends on how the original navigation was done. For example if the user navigated with the right arrow key, then DP4 navigates to the next field on the right again.
The exact details of this can get extremely complex, and there is no need to know them. However you do need to be aware of one very important rule:
An input field must NEVER be disabled as a result of entering data into it. For example you should never have logic like this:
case 1:
{
static int first_time = TRUE;
if (first_time)
{
inpm_x(&some_field);
first_time = FALSE;
}
else
inpm_omit();
}
|
For certain special keys, such as home and end, if there are several omitted fields, arriving at an enabled input field may take quite a few iterations, while the field number bounces around. In the worst case it may turn out that the key the user pressed cannot navigate to another field. In this case control should eventually return to the original field the user navigated away from. If that is now disabled too your program and the terminal manager will loop endlessly trying to find a field where data entry is possible. The program can usually be terminated with Ctrl+S Ctrl+C or Alt+F4 on Windows, but the user will not be happy.
The libtype 1 scheme explained above has one minor drawback. If the user actually enters data into a field, but then navigates away from the field in a way that would cause inpm_x() to return a non zero value, then the entered value may be lost in some circumstances. For example, DP4 utilities have a function inpm_number() which takes a short * parameter that represents the name of a field or table on the database. The initial number is translated to the name, and then inpm_s() is called. On return the entered value is converted back to a number. However entering a name and then pressing a key such as cursor down breaks, so the users name is not assigned to the short. Then the function gets called again with its old, and probably valid, initial value with jump TRUE, and input moves to the next field.
Although rather obscure, DP4 users did occasionally notice this problem. The problem was fixed, by inventing a new libtype: df_libtype 5. The only difference from df_libtype 1, is that internally when a field input function is going to return a non zero value, but with the field number still equal to the starting value, rather than returning the call is repeated, so that it will return 0 allowing validation to take place (but the original abort_code is now lost). Almost all DP4 utilities set df_libtype=5 now. However, if a program needs to know the original abort_code (for example if it uses one or more navigation keys in a non standard way, then using this df_libtype will cause problems.