Project

General

Profile

Terminal Management

Parts of the Screen

Before graphical user-interfaces (GUIs) were available in the Progress 4GL, all 4GL applications were character user-interface (CHUI). Everything on the screen (or terminal) of a CHUI based 4GL application is contained within a single entity called a Window. Since there is only ever one Window for a CHUI application and it covers the entire width and height of the screen, the terms Window, screen and terminal will be used interchangeably.

The 4GL Window consists two parts. The majority of the space is used for the display of user-defined frames. The rest of the space (the bottom three lines of the screen) is used to display messages (see below for the MESSAGE statement), status information (see the STATUS statement) and the insert mode indicator.

Consider the picture from a simple application:

In this picture the terminal window is divided into four areas. The colors used here are not normally shown, they are only used here to easily differentiate the borders of the different areas. In the real world all background/foreground colors are the same, for example white on black, and these colors can be modified by attributes from the COLOR statement or the COLOR phrase used in the respective screen related calls.

The black background is the area where user-defined frames are located. In this example, there are no user-defined frames displayed.

The bottom three lines of the terminal contains the remaining areas. The blue background is the area to display message statements. It occupies two lines. The last line (bottommost) of the screen is shared between the status line area marked in a yellow background and the insert mode indicator area showing in a red background.

The status line displays the help information for the current action, usually only when the user may enter input on the keyboard. For example, if you are editing a data field the status information can advise what keys can be pressed. If you a running a procedure without visible reactions, the status line can be used as a progress indicator. In this case, the programmer can explicitly control the text in the status area. This part of the screen can also be used to display help information when using the PAUSE statement or by changing the HELP attribute of the widget currently gaining input focus.

The last special part of the screen is the insert mode indicator area. It is used to inform the user about the current insert mode. This is only used when the user can edit and it cannot be explicitly controlled by the programmer. When insert mode is active, the next typed character will be inserted into the current cursor position push other input in that field to the side. In such a case, the word Insert will be displayed in the area(the bottom-right corner of the screen). When the mode is overwrite (the opposite of insert), the next character from the keyboard will replace the current one. The bottom right portion of the screen will remain blank when in overwrite mode. Both modes are only used when the user is actively editing in a widget.

Message Area

HIDE MESSAGE Statement

The HIDE MESSAGE statement clears the message area. By default, a pause will occur which must be explicitly passed (by the user pressing any key) before the message area will be cleared. If the NO-PAUSE option is present, no pause will occur and the message area will be cleared immediately.

Progress 4GL syntax:

HIDE MESSAGE [NO-PAUSE]

The corresponding Java syntax:

hideMessage(boolean noPause)

The parameter noPause will emit as true when the NO-PAUSE option is given in the 4GL and it will emit as false when NO-PAUSE is missing in the 4GL code.

The class implementing the hideMessage() method is the LogicalTerminal. We can use the short version cause we use a static import on the LogicalTerminal class so the short version becomes possible.

The possible usage of the HIDE MESSAGE statement can be seen from the following table:

4GL syntax Java converted Supported Notes
HIDE MESSAGE hideMessage(false) Yes Message hiding with pausing the execution and prompting the user for pressing any key.
HIDE MESSAGE NO-PAUSE hideMessage(true) Yes Message hiding without prompting the user for pressing any key.

Consider the simplest example of using the statement. The following code hides the message area and continues the execution without any pause:

message "Before hide message...".
hide message.
pause.

The corresponding Java syntax:

message("Before hide message...");
...
hideMessage(false);
...
pause();

After application starts the screen is:

After pressing a key the message is hiding and execution is suspending on the next PAUSE statement. The screen become:

There is one note for using this option. If there is a data update statement before HIDE MESSAGE statement there will be no pause generated for this statement. For example the following 4GL code declares the using of the pause:

message "Before hide message...".
update number1.
hide message.

And converting to the Java code as:

message("Before hide message...");
...
frame0.update(elementList0);
hideMessage(true);
...

But the application does not wait for the key pressing. Type any number in entry field. The screen become:

As you can see the HIDE MESSAGE statement was called without any pause despite on the pause declaration.

In the next example we use NO-PAUSE option. The respective 4GL code will be:

message "Before hide message...".
update number1.
hide message no-pause.
update number1.

Corresponding Java syntax:

message("Before hide message...");
...
frame0.update(elementList0);
hideMessage(true);
...
frame0.update(elementList1);

On the starting the screen will be:

Type any digit to update and see the message hiding without prompting any key to press.

Note the input focus is inside the editable field. This means we passed through the HIDE MESSAGE statement.

MESSAGE Statement

The MESSAGE statement is a tool to display short one or two line messages to inform the user about some special condition of the application control flow. Besides this informational purpose (output mode), it is possible to use the statement to obtain input from the user (input mode).

There are three types of the MESSAGE statement implementation: the output mode, input mode and the alert box (a popup message).

The summary of the possible MESSAGE statement sytax:

4GL syntax Java converted Supported Notes
MESSAGE [COLOR col] expression message(expression [, col]) Yes This is the message output form. It is used to display some information with an optionally redefined color attribute.
MESSAGE [COLOR col] expression { SET | UPDATE} field [FORMAT fmt] [AUTO-RETURN] message(expression, <set = true for SET, false for UPDATE>,
<field accessor>, <auto = true for AUTO-RETURN> [, fmt] [, col])
Yes This form is used to display information and take input from the user. Also known as the message input form.
MESSAGE [COLOR col] { expression | skip [(n)] }...
*VIEW-AS ALERT-BOX

[alert-type, BUTTONS button-set, TITLE title]
messageBox(expression [,new SkipEntity(n)] [, alert-type, button-set, title] [, col]) Yes The message will display in an alert box with a predefined button set and color attribute.

The SKIP option can be used to format the text in the alert box frame. The }... construction is a list of elements, either expressions or skips.
MESSAGE [COLOR col] { expression | skip [(n)] }...
*VIEW-AS ALERT-BOX

[alert-type, BUTTONS button-set, TITLE title]
[{ SET | UPDATE} field]
messageBox(expression,[new SkipEntity(n),] <set = true for SET, false for UPDATE>, <field accessor> [, alert-type, button-set, title] [, col]) Yes This is the extended version of the alert box style message with the possibility to get a logical return value when the alert box is dismissed.

The SKIP option can be used to format the text in alert box frame. The }... construction is a list of elements, either expressions or skips.
Output Mode

In this common case, all message output is directed to the two bottom lines of the screen starting with the height of the screen - 3. The format of the statement is:

Progress 4GL syntax:

MESSAGE [COLOR col] expression ...

Corresponding Java syntax:

message({java.lang.Object | java.lang.Object[]} expression ... [, ColorSpec color])

The expression is an object that can be either the single string or a list of objects for which a string representation will be concatenated (with interleaving spaces) before output. For more information and an example about the usage of the complex (list) form please see the part Alert-Box Mode of this document.

color is the object representing the color specification of the message rendering. It is possible to select the following values from the table:

4GL Syntax Java converted Description Supported
COLOR NORMAL new ColorSpec(ColorSpec.COLOR_NORMAL) Usual color/attribute values for your current terminal. Yes
COLOR INPUT new ColorSpec(ColorSpec.COLOR_INPUT) Color/attribute values for an input field as optionally defined in protermcap file if the system is UNIX/Linux, usually it is the default color with underlining. Yes
COLOR MESSAGES new ColorSpec(ColorSpec.COLOR_MESSAGES) This is the color/attribute values as optionally defined in protermcap file if the system is UNIX/Linux. The default value is reverse video compared to the COLOR_NORMAL Yes

The class ColorSpec allows construction of the color object based on the standard values in the 4GL. The well known color names can be passed in a string format to ColorSpec constructor. Otherwise, the ColorSpec constants can be used to identify the well known colors.

The optional attribute constant values COLOR BLINK, BRIGHT, RVV, UNDERLINE are not supported. At this time, customization of the color specification based on protermcap values is not supported.

This is the most simple case of the 4GL syntax:

message "Hello World!".

This will have the following result in a Java environment::

message("Hello World!");

Since there is no color phrase, the default color will be used. This means the message body will be represented with the reverse video color attribute which is the same as the ColorSpec.COLOR_MESSAGES.

This means that the following 4GL samples will also have the same result as the above example.

message color messages "Hello World!".

This will have the following result in Java environment::

message("Hello World!", new ColorSpec(ColorSpec.COLOR_MESSAGES));

The same result is obtained for this 4GL code:

message color messages "Hello” “World!".

Which results in the Java equivalent:

message(new Object[] { new character("Hello"), new character("World!")},
        new ColorSpec(ColorSpec.COLOR_MESSAGES));

As you can see the format of the expression argument has been changed here. We have an Object[] container with the list of entries instead of a single String or character expression. The one character empty space separator has been automatically inserted by the FWD runtime in this case.

The screen result for all 3 examples is identical and is shown below.

Input Mode

Sometimes it is useful to include the possibility to read the user choice using a message statement. For example if the application needs the user to select the application control flow or to change/update the value of a variable. The MESSAGE statement has such possibility.

Progress 4GL syntax:

MESSAGE [COLOR col] expression ... { SET | UPDATE} field [FORMAT fmt] [AUTO-RETURN]

Which has the corresponding Java equivalent:

message({java.lang.Object | java.lang.Object[]}expression ...,
        boolean <set = true for SET, false for UPDATE>,
        Accessor <field accessor>, boolean <auto = true for AUTO-RETURN>
        [, java.lang.String fmt] [, ColorSpec color])

The expression ... means it is possible to use either single expression (including a literal) or instead to provide an object containing the list of the expressions to be concatenated. For more information and an example about the usage of the complex object case, please see the part Alert-Box Mode section of this chapter.

Both the first and second parameters follow the same usage pattern as in the output mode case.

The third parameter (SET or UPDATE) defines that this is an input form. In Java, the parameter will be true in the case of SET and false in the case of UPDATE.

field accessor is either new AccessorWrapper(<variable>) for variables and new FieldReference(<buffer>, "<field name>") for record fields. This is the way that the business logic passes a variable or database field to the FWD runtime so that the runtime can edit that value. The assignment of that new value (based on the user's edits while in the message statement) is done on behalf of the calling code (business logic). When the message() method returns, if the edit was successful, the user's input will be available in the given variable or database field.

auto AUTO-RETURN if we want to use 4GL AUTO-RETURN option. This means RETURN is automatically generated when the field is full (based on the default or given format string that governs the edit).

fmt is the format string for updated variable/field.

The format table of the usable variable formats and default values for the formats(see data format related chapter for details).

Data Type Default Display Format Supported
CHARACTER x(8) Yes
DATE 99/99/99 Yes
DECIMAL ->>,>>9.99 Yes
HANDLE >>>>>>9 Yes
INTEGER ->,>>>,>>9 Yes
LOGICAL yes/*no* Yes
MEMPTR Indirect usage 1 Not recommended 2
RAW Indirect usage 1 Not recommended 2
RECID >>>>>>9 Not recommended 2
ROWID Indirect usage 1 Not recommended 2
WIDGET-HANDLE This is a instance of the HANDLE Yes

Note 1 . means it is not possible to use the data type directly. However it is possible to convert to the character string representation before calling the message statement.

Note 2 . means it is supported but not recommended to use because modification of the variable can be dangerous or data object does not allow the changes to be committed.

color is the color object representing the color specification of the message rendering the same way as it is used in message statement described in output mode.

There are some constraints that must be taken into account while using message in input mode. First if the message and the variable format will exceed the maximum width of the terminal, the 4GL and converted Java counterpart will truncate the message text to fit the variable. Leaving space for the editing operation has higher priority in placement than the output. This feature has been implemented in Java the same way as it exists in original 4GL code. There is no difference in behavior.

The second constraint is related to decimal values with non-significant zeros to the right of the decimal point. These zeros will not be displayed into message area. Again the Java implementation shows the same behavior as original 4GL code.

If the output is redirected to the file stream the value being updated within the message input mode will not be written to the file. This is the feature of the both 4GL original code and Java implementation.

In the example below we change a variable which has an initial value of 2 and redisplay again to verify the value has been changed. Consider the following Progress 4GL:

def var number1 as int init 2.

message color messages "Update the integer variable:" update number1 format "999" auto-return.
message color normal "Update the previously updated variable:" 
        update number1 format "999" auto-return.

In Java, the result is this:

integer number1 = new integer(2);
...
message("Update the integer variable:", false, new AccessorWrapper(number1), true, "999",
        new ColorSpec(ColorSpec.COLOR_MESSAGES));
message("Update the previously updated variable:", false, new AccessorWrapper(number1), true,
        "999", new ColorSpec(ColorSpec.COLOR_NORMAL));

During the first message statement the screen looks like this:

Type 10 into the field to update the variable and see the changed value:

To demonstrate auto == true on the first screen press 100 to complete the field. The application automatically goes to the screen:

The following is an example of message redirection. If you duplicate output to the file the message() call will print data except the value of the variable to be changed by UPDATE option of the message() call. For example consider the following 4GL code:

output to msg_train4.txt.

message "Single message".
message "Enter any integer value: " update n as int.

output close.

Here is the Java equivalent:

integer n = new integer(0);
...
UnnamedStreams.assignOut(StreamFactory.openFileStream("msg_train4.txt", true, false));
message("Single message");
message("Enter any integer value: ", false, new AccessorWrapper(n));
UnnamedStreams.closeOut();

Type any integer value into updated field. The screen will look like this:

The content of the output file msg_train4.txt is:

Single message
Enter any integer value:

The following is the example of the text truncating for the case when there are no more room to fit everything specified for output:

4GL code:

DEFINE VARIABLE truncVar AS CHARACTER FORMAT "x(60)".

MESSAGE "abcdefghijklmnopqrstuvwxyz" UPDATE truncVar.

Java implementation:

public static final String FMT_STR_1 = "x(60)";
...
message("abcdefghijklmnopqrstuvwxyz", false, new AccessorWrapper(truncVar), FMT_STR_1);
...

The length of the message constant "abcdefghijklmnopqrstuvwxyz" plus the format declaration “x(60)” exceeds the terminal window width. The screen will look like this:

Another note is related to the decimal values with insignificant zeros to the right of the decimal point. Consider the following example:

4GL code:

DEFINE VARIABLE decValue AS DECIMAL FORMAT ">>9.99" INITIAL 2.10.

MESSAGE "This is the truncated decimal" decValue.

and the Java equivalent:

public static final String FMT_STR_1 = ">>9.99";
...
      decimal decValue = new decimal(2.10);
...
         message(new Object[]
         {
            "This is the truncated decimal", decValue
         });
...

Note the FMT_STR_1 format string is not inserted into the message statement because in this case we do not allow to edit or update the statement. In this example the valid decimal value 2.10 with correct format will be truncated to eliminate the non-significant right 0. The resulting value on the screen is 2.1:

Alert-Box Mode

Another possible usage of the MESSAGE statement is to generate a popup or dialog message box in its own separate frame. There are the two different versions of this call. One is to display information and pause program execution. The other can be used to update a logical variable (it is equivalent to having a return value from the alert-box). The format of these calls are:

4GL syntax for the simple display form:

MESSAGE [COLOR col] { expression | skip [(n)] }...
    VIEW-AS ALERT-BOX [alert-type, BUTTONS button-set, TITLE title]

4GL syntax for the display and logical variable update form:

MESSAGE [COLOR col] { expression | skip [(n)] }...
    VIEW-AS ALERT-BOX [alert-type, BUTTONS button-set, TITLE title]
    { SET | UPDATE} field

Converted Java result for the display-only form:

messageBox({java.lang.Object | java.lang.Object[]} expression [,new SkipEntity(n)]
           [, int alert-type, int button-set, java.lang.String title] [, ColorSpec col])

Converted Java result for the display and update form:

messageBox({java.lang.Object | java.lang.Object[]} expression,[new SkipEntity(n),]
           boolean <set = true for SET, false for UPDATE>, Accessor <field accessor>
           [, int alert-type, int button-set, java.lang.String title] [, ColorSpec col])

The defined above element ... is required in clarification. This construct means we can use either single element or an object representing a list of elements. In the list case, every entry of this list can be either an expression or the skip(n) element. The FWD implementation is slightly different.

This 4GL example code:

message "Single entry message" view-as alert-box information buttons ok title "Information".

will be converted as this Java code:

messageBox("Single entry message", ALERT_INFO, BTN_OK, "Information");

While the 4GL statement:

message "Entry message line 1" "to be continued" skip "Entry message line 2. PI =" pi skip(1)
        "Entry message line 3" skip(2) "Entry message line 4" skip(3) "Entry message line 5" 
        view-as alert-box information buttons ok title "Information in a list format".

will be implemented as:

messageBox(new Object[]
{
   "Entry message line 1",
   "to be continued",
   new SkipEntity(),
   "Entry message line 2. PI =",
   pi,
   new SkipEntity(1),
   "Entry message line 3",
   new SkipEntity(2),
   "Entry message line 4",
   new SkipEntity(3),
   "Entry message line 5" 
}, ALERT_INFO, BTN_OK, "Information in a list format");

In the list case, an Object[] is passed instead of the single entry. Two sequential string literals are not concatenated to the single literal but are implemented as different entries in the list. This allows the runtime to duplicate the behavior of the 4GL for such statements, since these elements must be put together into a single output buffer. The use of the variable pi as one of the entries in this list demonstrates the possibility of mixing constants and other kinds of more complex expressions in a single list object.

On the runtime level the "FWD":mailto:P J constructs the *AlertBox()* class passing the array list as one of the arguments to the constructor of the class. The runtime converts the elements of the array list to their string representation. Based on the current screen and frame sizes, the text is relocated inside the AlertBox frame calculating the required frame width and position. The screen for this case will look like this:

The following constants for alert-type field have been defined in FWD class LogicalTerminal and are available for usage:

4GL FWD Supported
MESSAGE ALERT_MESSAGE Yes
QUESTION ALERT_QUESTION Yes
INFORMATION ALERT_INFO Yes
ERROR ALERT_ERROR Yes
WARNING ALERT_WARNING Yes

The following constants for the button-set field have been defined in FWD the class LogicalTerminal and are available for usage to preselect the desired button set:

4GL FWD Supported
YES-NO BTN_YES_NO Yes
YES-NO-CANCEL BTN_YES_NO_CANCEL Yes
OK BTN_OK Yes
OK-CANCEL BTN_OK_CANCEL Yes
RETRY-CANCEL BTN_RETRY_CANCEL Yes

There are constraints for usage of alert-box message statements:

  • The only variable type that can be updated in this messageBox() function is the logical type. It is set to true if the Yes or OK button is pressed and to false if the No button is selected. When the Cancel button is selected, the value of the logical variable is set to the unknown value.
  • The UPDATE option (but not SET) uses the current value of the logical variable to select the default choice button (which will be highlighted).

The option skip(n) can be used in this type of the MESSAGE statement to format the text inside the alert-box by breaking long content into multiple lines.

Consider some examples. The following is a simple dialog-box used only for information display purposes. Pressing OK just resumes the application execution.

4GL source:

message "This is the Hello World! inside the simple dialog box" 
        view-as alert-box information buttons ok title "Information message".

The resulting Java code:

messageBox("This is the Hello World! inside the simple dialog box", ALERT_INFO, BTN_OK,
           "Information message");

The screen will look like this:

The following more advanced example shows the possibility of updating a logical variable. In this code the variable boolChoice has an initial value and it can be seen as the selected button. Depending on the user choice, an additional message displays. This also shows the use of the skip(n) construct to manually separate the message body. Otherwise the message text will be output as a single line.

The Progress 4GL code:

def var boolChoice as logical init true.

message "This is the upper part of the message before the skip(1) statement" SKIP( 1 )
        "You have opportunity to change the logical var behind the dialog" 
        "the default button(var value) is initially selected." 
        view-as alert-box question buttons yes-no-cancel
        title "Make your selection" update boolChoice as logical.

case boolChoice:
...
   when no then
      do:
         message "You have chosen NO button.".
      end.
...
end case.

The Java implementation:

logical boolChoice = new logical(true);
...
public void body()
{
   messageBox(new Object[]
   {
      "This is the upper part of the message before the skip(1) statement",
      new SkipEntity(1),
      "You have opportunity to change the logical var behind the dialog",
      "the default button(var value) is initially selected." 
   }, false, new AccessorWrapper(boolChoice), ALERT_QUESTION,
      BTN_YES_NO_CANCEL, "Make your selection");

   logical condition0 = boolChoice;
...
   else if (condition0.equals(new logical(false)))
   {
      message("You have chosen NO button.");
   }
...
}

The screen at the start of the messageBox() call is:

If the No button is selected, the screen will look as follows:

MESAGE-LINES Function

This simple function returns the number of the lines at the bottom of the screen which are dedicated to display message information.

The Progress 4GL syntax:

MESSAGE-LINES

The corresponding Java syntax:

getMessageLines()

The function is defined in the LogicalTerminal class. In the example below we walk through the message lines and display the message at the every line we have in a current terminal.

The 4GL code:

define variable i as integer.
do i = 1 to message-lines:
   message "This is the message line number" i.
end.

Which is implemented in Java as:

integer i = new integer(0);
...
for (i.assign(1); _isLessThanOrEqual(i, getMessageLines()); i.increment())
{
   message(new Object[]
   {
      "This is the message line number", i
   });
}

The resulting screen will look like the following:

Status Area

It is possible to directly manipulate the text displayed in the status line. The 4GL STATUS statement provides this feature. In Java, these different versions of the STATUS statement are implemented differently. There is a set of functions defined in LogicalTerminal to manipulate the status line.

STATUS DEFAULT Statement

This replaces the default status line message when a user is running a procedure. The default status line value for the STATUS DEFAULT statement is empty line. The case when this status is displaying is the long running procedure without any input possible action or inner loops like REPEAT. The expression must be either a character based expression or a string literal (constant enclosed in quotes). For example: STATUS DEFAULT “my”+var+”character”+ my-function(). If you do not specify an expression, the status line output resets to the original value.

The Progress 4GL syntax:

STATUS DEFAULT expression

The Java syntax:

statusDefault({character | java.lang.String }expression) or
statusDefault({character | java.lang.String }expression, boolean noLengthLimit)

The second version is used to ignore the Progress 4GL limitation of 63 characters for the maximum length of the status line. In this case the noLengthLimit should be set to true.

The following example demonstrates the usage of the complex expression as the argument. The 4GL code can be like:

def var chWait as character init "Wait, wait, wait... or press ".
STATUS DEFAULT chWait + kblabel("END-ERROR") + " if tired".

The corresponding Java synatx:

character chWait = new character("Wait, wait, wait... or press ");
...
   statusDefault(concat(chWait, kbLabel("END-ERROR"), " if tired"));

The screen will be the following:

The next example demonstrates returning to the default value for STATUS DEFAULT statement. The 4GL code will be:

status default.

Having the Java implementation syntax:

statusDefault();

And the screen becomes:

STATUS INPUT Statement

This replaces the default “Enter data or press F4 to end.” status line message when a user is entering data into a frame data field. The expression must be either a character expression or a string literal (constant enclosed in quotes). For example: STATUS DEFAULT “my” + var + ”character” + my-function(). If you do not specify an expression the input status line output resets to the default “Enter data or press F4 to end.”.

The Progress 4GL syntax for changing the status line while editing:

STATUS INPUT expression

The Java syntax:

statusInput({character | java.lang.String} expression)

The Progress 4GL syntax for resetting the editing status line:

STATUS INPUT OFF

The Java syntax:

statusInputOff()

As opposed to the statusInput(expression) call, statusInputOff() disables any input status line messages.

The example below shows both statusInput(expression) and statusOff() calls. First the input status line is replaced with an alternative. Then the status line is disabled. Finally, the status line's default behavior is restored.

The 4GL code sample:

STATUS INPUT "Alternative status line. Enter data, or use the " + KBLABEL("END-ERROR") +
" key to exit".
message "Enter any integer value: " update n as int.
status input off.
message "Enter any integer value: " update n as int.
status input.
message "Enter any integer value: " update n as int.

This will result in the following Java code:

statusInput(concat("Alternative status line. Enter data, or use the ", kbLabel("END-ERROR"),
                   " key to exit"));
message("Enter any integer value: ", false, new AccessorWrapper(n));
statusInputOff();
message("Enter any integer value: ", false, new AccessorWrapper(n));
statusInput();
message("Enter any integer value: ", false, new AccessorWrapper(n));

The screen after displaying the first message is:

Then type any integer data and see the disabled status line:

Then type another integer and see the default status become restored:

The second example demonstrates the usage of the statusDefault(expression) call. To exit you can press F4. The first REPEAT loop has the modified status. The second use restores the default status.

4GL source code

status default "Wait, wait, wait... or press F4 if tired".
repeat:
   pause 1 no-message.
end.
status default.
repeat:
   pause 1 no-message.
end.

will be implemented in Java as:

statusDefault("Wait, wait, wait... or press F4 if tired");
repeat("loopLabel0", new Block()
{
   public void body()
   {
      pause(1, (String) null);
   }
});

statusDefault();
repeat("loopLabel1", new Block()
{
   public void body()
   {
      pause(1, (String) null);
   }
});

When the application is started, the screen has the following status line:

Press F4 to restore the default one:

The status information line can be overwritten by the further messages from the PAUSE statement or HELP attribute that is used to display the help info when input focus moves to a widget that has a non-default HELP property.

The results of using the statements STATUS DEFAULT, STATUS INPUT OFF or STATUS INPUT in a session remain in effect for all the procedures run in the session, unless overwritten by subsequent STATUS related statements in the same session.

Insert Mode Indicator

The insert mode indicator cannot be directly controlled by the 4GL programmer. In other words, no 4GL statements, functions, methods or attributes exist to manipulate or query the state of the insert mode indicator. For this reason, FWD likewise does not provide any such features. The indicator state is tied to the state of widgets being edited and the FWD runtime strives to exactly duplicate the behavior of the 4GL in this regard.

Direct Terminal Manipulation

PUT CURSOR Statement

The other tool to manipulate screen directly is the PUT CURSOR statement. Using it moves the current terminal cursor to the desired location and makes it visible. Usually in data handling statements such as UPDATE, SET, PROMPT-FOR, EDITING and INSERT the cursor is visible when the user modifies the current data value so it is possible to see where the cursor is. However, if the data is entered through a READKEY statement and it is not a part of an EDITING block the cursor is not seen and this is a tool to make it visible.

The usage of PUT CURSOR OFF will disable (and render invisible) the terminal cursor.

The Progress 4GL syntax:

PUT CURSOR ROW r COLUMN c

or

PUT CURSOR OFF

These are replaced with the Java equivalents:

putCursor({double | NumberType} r, {double | NumberType} c)

or

putCursor(boolean false)

respectively.

r, c are the row and column cursor coordinates respectively. If the coordinates are outside of the current screen the cursor will not be repositioned.

The call putCursor(false) turns the visibility cursor off.

This is a kind of direct screen manipulation, so this is often paired with the use of the 4GL statements PUT SCREEN to output text directly to the terminal and READKEY to read user input. In any case, it is up to developer to keep track and store the current cursor position.

The putCursor(r, c) will display the cursor until the putCursor(false) is called to stop display.

Because the cursor is always visible in an EDITING phrase using the putCursor(r, c) statement (if you not issued putCursor(false) before) might produce the errors.

Consider the following example. The idea is to use putCursor(r, c) to simulate the editor frame. The application waits for a key press and either types the character into the current position or moves the cursor if using the arrow keys or removes the character in response to backspace.

To exit the repeat loop - press F1 or F4. In case of the GO (F1) key pressing the second frame displays on the screen with a duplication of the variable content. In this code there is no focusable widget defined in any frame.

putScreen() is used to display the interpretation of the current key pressed when using putCursor().

Consider the following 4GL example:

PUT CURSOR ROW r COLUMN c.
READKEY.
...
IF LASTKEY >= 32 AND LASTKEY <= 126 THEN DO:
   PUT SCREEN ROW r COLUMN c KEYLABEL(LASTKEY).
...
END.

This will be implemented in Java as:

putCursor(r, c);
KeyReader.readKey();
...
if (_and(isGreaterThanOrEqual(lastKey(), 32), isLessThanOrEqual(lastKey(), 126)))
{
   putScreen(keyLabel(lastKey()), r, c);
...
}

The variables r and c are introduced to keep track on the current cursor position. It is up to developer to do this because there are no internal tools to do this for direct screen calls like this.

The screenshot of the application last stage:

PUT SCREEN Statement

The 4GL PUT SCREEN statement allows arbitrary text to be written directly to the terminal.

This is converted to the usage of functions defined in LogicalTerminal class that can be used for direct manipulation with on screen data.

The Progress 4GL syntax:

PUT SCREEN [COLOR color] [COLUMN c ROW r] expression

The Java syntax:

putScreen({character | java.lang.String} expression
          [,{double | NumberType} row, {double | NumberType} column] [, ColorSpec color])

expression - String variable to be displayed on the screen

row, column - Screen coordinate of the row and column to be used for the rendering starting location.

color - Color specification. See the MESSAGE statement for the color specification details.

There is one consideration which must be taken into account when using PUT SCREEN call. The values displayed by PUT SCREEN do not work the same as values output via a frame and it's widgets. The output can be displayed over existing screen data in a current frame lifetime. Any output of PUT SCREEN over a portion of a regular 4GL frame will be erased the next time that the frame outputs to the same location. Moreover any further screen updates of the current frame will not hide the parts of the PUT SCREEN output not overwritten by the current screen changes. The PUT SCREEN will be completely cleared only when the current frame is hidden from the screen or all areas of the PUT SCREEN output are otherwise overwritten with new content.

When using PUT SCREEN call inside the procedure that runs in batch or background mode such output will be disregarded in the 4GL. Currently, this is not the case in FWD.

PUT SCREEN output in the message lines area will not be cleared by usage of HIDE MESSAGE. This can be viewed as “garbage” on the screen. But this is the native 4GL behavior and it is reproduced in Java converted application too.

An example in 4GL:

def var hello as char init "Hello World".

put screen row 10 column 23 "+------------------------------+".

put screen row 11 column 23 "|".
put screen color messages row 11 column 32 hello.
put screen row 11 column 54 "|".

put screen row 12 column 23 "|".
put screen color input row 12 column 32 hello.
put screen row 12 column 54 "|".

put screen row 13 column 23 "|".
put screen color normal row 13 column 32 hello.
put screen row 13 column 54 "|".

put screen row 14 column 23 "+------------------------------+".

and implemented in Java:

character hello = new character("Hello World");
...
public void body()
{
   putScreen("+------------------------------+", 10, 23);

   putScreen("|", 11, 23);
   putScreen(hello, 11, 32, new ColorSpec(ColorSpec.COLOR_MESSAGES));
   putScreen("|", 11, 54);

   putScreen("|", 12, 23);
   putScreen(hello, 12, 32, new ColorSpec(ColorSpec.COLOR_INPUT));
   putScreen("|", 12, 54);

   putScreen("|", 13, 23);
   putScreen(hello, 13, 32, new ColorSpec(ColorSpec.COLOR_NORMAL));
   putScreen("|", 13, 54);

   putScreen("+------------------------------+", 14, 23);
}

In this example, text is output to the screen with three different color attributes. This also shows some variation of usage the String constants and variables. The screen looks like this:

TERMINAL Function

This function returns the currently used terminal type for the session. The result depends upon the underlining operating system and environment. For example, in the Windows graphical interface, the function returns WIN3. On Windows in a character interface the function returns CO80, BW80 or MONO depending on the monitor type. On UNIX/Linux environment, TERMINAL returns the value of the $TERM environment variable for a given session. It is possible to have different terminal types for different sessions in this case.

The 4GL syntax:

TERMINAL

will be implemented in Java as:

getTerminalType()

This static method is defined in LogicalTerminal class. The simple code to retrieve the terminal type in 4GL is:

message "The currently using terminal is:" terminal.

implemented in Java as:

message(new Object[]
{
   "The currently using terminal is:", getTerminalType()
});

After this application is started, the screen for the vt320 terminal on Linux will be:

TERMINAL Statement

The TERMINAL statement allows changing the terminal type dynamically during program execution. On UNIX/Linux this will change the value of the TERM environment variable for the current session.

In 4GL the statement syntax:

TERMINAL = termid

The Java syntax:

setTerminalType({character | java.lang.String} termid)

The termid is character object or String instance to be used as the replacement for the current terminal type.

This static method is defined in LogicalTerminal class.

The TERMINAL statement does not change the physical characteristics of a terminal. The new type must be valid, known to the system and supported by the physical hardware.

The changes made by TERMINAL statement cause a reinitialization of the terminal. In the 4GL this means the definitions taken from protermcap file are re-processed. In the FWD environment, NCURSES provides the terminal support, so this is the environment that will be reinitialized.

It is possible that key configuration will change during this re-initialization. This may manifest as problems in the ON statement with changed function keys.

This sample of the terminal redefinition in 4GL:

terminal = "vt220".
message "The currently using terminal is:" terminal.

will be implemented in Java as:

setTerminalType("vt220");
message(new Object[]
{
   "The currently using terminal is:", getTerminalType()
});

The screen on Linux will be:

The special form of the statement is:

TERMINAL = TERMINAL

is implemented as another Java method:

resetTerminal();

This call reinitializes the terminal without changing the terminal type.

Key Processing

Here is the list of the useful key handling related function to be used in FWD application.

4GL syntax Java converted Supported Description
READKEY [STREAM stream][n] KeyReader.readKey([stream][, n]) Yes Reads a the next typed key or the next character from the input data stream.
LASTKEY KeyReader.lastKey() Yes Returns the last pressed key.
KEYFUNCTION LogicalTerminal.keyFunction(keycode) Yes Get the function name of the key for the given code.
KEYCODE LogicalTerminal.keyCode(keylabel) Yes Get the integer key code for a given label.
KEYLABEL LogicalTerminal.keyLabel(keycode) Yes Returns the label of the given keycode if it exists.
ON key-label key-function remapKey(key-label, key-function) Yes Redefine the key with the given key label to execute new key function.

READKEY statement

READKEY obtains the next character available from the terminal or a stream. If no character is available, it will block and an optional timeout can be specified (which will abort the wait after that many seconds if there is still no character available).

The Progress 4GL syntax:

READKEY [STREAM stream] [PAUSE n]

The Java syntax:

KeyReader.readKey([Stream stream] [,{double | NumberType} n])

When reading from the terminal, this blocks program execution until a character is available on the unnamed input stream. The terminal will buffer incoming keystrokes (in the type-ahead buffer). If the type-ahead buffer has characters in it, they will be returned in a FIFO order. Otherwise, the statement will block waiting for input from the keyboard. Any character that is read can be accessed via the LASTKEY function. This terminal form of READKEY is the default unless a stream is explicitly specified.

If not reading from the unnamed input stream, stream is the source to read from. The stream can be a file or it can be a child process. The READKEY will return the next character available or it will block until a character is available. The result is accessed via the LASTKEY function.

n is the maximum wait time in seconds. If this is specified, the function returns after the time frame even if no key was pressed. In this case the LASTKEY become -1. On UNIX systems this option can be used to do polling through pipes.

The first example here is using the READKEY without timeout. The 4GL code is:

readkey.
message "The lastkey value is:" lastkey.

Will be implemented in Java as:

KeyReader.readKey();
message(new Object[]
{
   "The lastkey value is:", lastKey()
});

After starting application goes to the infinite loop in READKEY. Press the ENTER key. The program goes to the next step and the screen become:

The next example demonstrates the non-zero timeout. 10 seconds. In 4GL syntax the code will be:

readkey pause 10.
message "The lastkey value is:" lastkey.

Will be implemented in Java as:

KeyReader.readKey(10);
message(new Object[]
{
   "The lastkey value is:", lastKey()
});

After starting, wait for a 10 seconds, the screen become as if we do not press any key:

Press the DELETE key within 10 seconds. The screen will be different:

The next example demonstrates the using of the non-terminal stream to use the READKEY statement. The 4GL code is:

input from "readkey_training3.txt".
readkey.
message "The lastkey value is:" lastkey.

Will be implemented in Java as:

UnnamedStreams.assignIn(StreamFactory.openFileStream("readkey_training3.txt", false, false));
KeyReader.readKey();
message(new Object[]
{
   "The lastkey value is:", lastKey()
});

The READKEY gets the first available byte from input file. In our case the file contents has the only char - 9. This is the 0x39 in hex an 57 in decimal. So after application starts the screen become:

If called with zero delay READKEY returns immediately with LASTKEY -1 as in an example below:

This 4GL code:

readkey pause 0.
message "The lastkey value is:" lastkey.

will be implemented in Java as:

KeyReader.readKey(0);
message(new Object[]
{
   "The lastkey value is:", lastKey()
});

The output of the application is:

The usage of the READKEY intercepts any input from the user. To pass input to a widget for processing, the APPLY statement can be used.

The READKEY blocks the application until a character is read or the timeout occurs. No widgets will receive the input focus before READKEY returns.

If READKEY encounters an invalid character, LASTKEY is set to -1. In case of it reads the EOF character, the value of LASTKEY is -2.

The FWD environment does support Unicode internally. When the readKey() gets the data from the external file or another process via pipe FWD takes into account the current locale setting - in Linux this is the value of the current LANG variable and translates the character from that character set into the Unicode representation. The opposite process happens when FWD writes data into pipe or external file. Unicode characters are converte into the character data stream according to the currently used locale.

Double Byte Character Sets (DBCS) are not currently supported or are only partially supported. For example, only Single Byte Character Sets (SBCS) can be used with the terminal (input or output). However, some forms of stream usage may allow DBCS text depending on the currently configured locale setting. The details of using READKEY with streams can be found in respective chapter of this book called Streams in Part 4 of this book.

LASTKEY Function

The function LASTKEY is used to retrieve the integer code of the most recent character read by READKEY. The source is the keyboard or data stream during interaction with the procedure.

The Progress 4GL syntax:

LASTKEY

The Java syntax:

KeyReader.lastKey()

An example of LASTKEY usage:

message "Press any key...".
readkey.
message "You have pressed key:" lastkey "with function:" keyfunction(lastkey)
        "and label:" keylabel(lastkey).

This is converted to the following Java code:

message("Press any key...");
KeyReader.readKey();
message(new Object[]
{
   "You have pressed key:", lastKey(), "with function:", keyFunction(lastKey()),
   "and label:", keyLabel(lastKey())
});

If the user presses the Insert key, the screen will look like this:

LASTKEY will return -1 in case the last READKEY was timed out or a recently used PAUSE was timed out.

In case of using the READKEY statement with the PAUSE option, the value of the LASTKEY is the key pressed to end the PAUSE.

The initially value (before any user input or usage of READKEY) of LASTKEY is dependent upon the currently used terminal type. For example it is 401 for terminals xterm/vt100 and -1 for vt220/vt320 and wyse60. For other terminal types it is unknown at this time.

In case of reading data from a file the LASTKEY is set to the last character read from the file. When reaching the end of the file (EOF) the value of the LASTKEY will be set to -2.

KEYFUNCTION Function

The function KEYFUNCTION is used to convert the integer key code, for example obtained from LASTKEY, to a character value. The parameter can be a constant, variable, field or a complex expression.

The Progress 4GL syntax:

KEYFUNCTION(keycode)

The Java syntax:

LogicalTerminal.keyFunction(integer keycode)

keycode is the integer key code.

The example of usage in 4GL:

readkey.
func = keyfunction(lastkey).
message "The key function value is:" func.

will be implemented in Java as:

KeyReader.readKey();
func.assign(keyFunction(lastKey()));
message(new Object[]
{
   "The key function value is:", func
});

The output for the up arrow key is:

The value returned by KEYUFUNCTION is affected by any ON statements used to redefine the key represented by the expression.

If there is no function assigned to the current expression value or the function is BELL the KEYFUNCTION returns the unknown value. The KEYFUNCTION(-2) equals the ENDKEY.

KEYCODE Function

The function KEYCODE is used to calculate the integer key code for given key label according to the current translation table.

The Progress 4GL syntax:

KEYCODE(keylabel)

The Java syntax:

LogicalTerminal.keyCode({character | java.lang.Stream} keylabel)

keylabel is a string representing the label of the key for which a code is to be computed. Can be the constant, field, variable name or expression.

The example of usage in the 4GL:

message "The key code of the CURSOR-DOWN is:" keycode("cursor-down").

will be implemented in Java as:

message(new Object[]
{
   "The key code of the CURSOR-DOWN is:", keyCode(new character("cursor-down"))
});

The output will be the following:

KEYLABEL Function

The function KEYLABEL returns the string with the label of the key for the given key code.

The Progress 4GL syntax:

KEYLABEL(keycode)

The Java syntax:

LogicalTerminal.keyLabel(integer keycode)

keycode is the integer code of the key whose label is to be calculated.

The example code in the 4GL:

readkey.
lbl = keylabel(lastkey).
message "The key label value is:" lbl.

implemented in Java as:

KeyReader.readKey();
lbl.assign(keyLabel(lastKey()));
message(new Object[]
{
   "The key label value is:", lbl
});

lbl is a character variable to obtain the label of the key in this example. The output if the TAB key is pressed will be:

Some key codes can be associated with more than one key label. In this case FWD will return the first available one. This is the same behavior as we have in original 4GL code.

ON Statement (for Remapping Keys)

This form of the ON statement only addresses the usage for remapping keys to key functions. For other details regarding the ON statement, please see the Triggers and Events chapter.

Although Progress has defined functions for several of the keys on a keyboard, sometimes it is required to change the default action happening when the user presses some key. There are two ways to do this. First you can make the global system wide changes. In the 4GL on UNIX-like systems this is done editing the protermcap file.

FWD is dependent upon NCURSES on UNIX or Linux systems, so the way to control default settings is to edit the terminfo definitions. However this way has a side effect. The changes you made will touch all terminal applications, not just the converted 4GL code. Even more than the Progress 4GL code considered here.

Progress 4GL provides another way to redefine the key action. The ON statement can be used to remap key labels to key functions.

The Progress 4GL syntax:

ON key-label key-function

The Java syntax:

remapKey({character | java.lang.String} key-label, {character | java.lang.String} key-function)

key-label is the character label of the key to redefine. Usually in UNIX-like systems the default set is declared in the protermcap file for 4GL.

The key-function is the character based new function you want to associate with the given key-label. The valid key-function substitutions can be seen in the following table. In the right column of the table you can see the default keys for the given function:

Function to Redefine Default Key
BACKSPACE BACKSPACE
BACK-TAB SHIFT-TAB, CTRL-U, CODE-TAB
BELL 1 -
CLEAR F8, CTRL-Z, CODE-Z
CURSOR-UP standard gray arrow keys on keyboard, CTRL-K
CURSOR-DOWN standard gray arrow keys on keyboard, CTRL-J
CURSOR-LEFT standard gray arrow keys on keyboard, CTRL-H
CURSOR-RIGHT standard gray arrow keys on keyboard, CTRL-L
DELETE-CHARACTER DEL
ENDKEY -
END-ERROR F4, CTRL-E, CODE-E, ESC
ERROR -
GO F1, CTRL-X, CODE-X
HELP 1 F2, HELP, CTRL-W, CODE-W
HOME HOME, ESC-H(UNIX)
INSERT-MODE F3, INSERT, CTRL-T, OVERTYPE
RECALL F7, CTRL-R, CODE-R
RETURN RETURN
STOP CTRL-BREAK, CTRL-C(UNIX)
TAB TAB, CTRL-I

Note 1 . not supported in Windows character based interface

In the 4GL example below the key F1 is remapped to the HELP function:

message "Press F1 key ...".
readkey.
message "The legacy key function for F1 is:" keyfunction(lastkey).
on F1 HELP.
message "Press the same key again...".
readkey.
message "The remapped key function for F1 is:" keyfunction(lastkey).

This is implemented in Java as:

message("Press F1 key ...");
KeyReader.readKey();
message(new Object[]
{
   "The legacy key function for F1 is:", keyFunction(lastKey())
});
remapKey("F1", "HELP");
message("Press the same key again...");
KeyReader.readKey();
message(new Object[]
{
   "The remapped key function for F1 is:", keyFunction(lastKey())
});

The screen before remapKey() is:

And after remapKey():

The result of the ON statement used to redefine an key function in the terminal remains in effect until the next ON statement for the same key or until the end of the current session.

PAUSE Statement

The PAUSE statement suspends processing indefinitely, for specified amount of time or until the user presses any key. There are several form of this statements. The general 4GL format of the statement is:

PAUSE [ n ] [ BEFORE-HIDE ] [ MESSAGE message  |  NO-MESSAGE ] [ IN WINDOW window ]

The different forms are summarized in the following table:

4GL Syntax Supported Description
PAUSE Yes Waits for an indefinite amount of time. Can be resumed by a key press.
PAUSE [ n ] Yes Waits for a n seconds before resuming.
PAUSE [n] BEFORE-HIDE Yes Specifies that a pause will occur (implicitly) before a frame is hidden.
PAUSE { MESSAGE message | NO-MESSAGE } Yes Redefines the default message line displayed in status line when the PAUSE is in action or not to display any message line if NO-MESSAGE option is declared
PAUSE { IN-WINDOW window } No Specifies the window to apply the PAUSE. In CHUI there is only such window. Not supported in FWD at this time.

The keyboard type-ahead buffer will be cleared before any pause, discarding any type-ahead characters.

All supported options can be combined into single statement. Each supported statement form will be considered separately below.

PAUSE [n]

This is the most simple form of the statement. The optionally specified n value is the time interval in seconds after which the execution will be resumed even if the user does not press a key.

The 4GL syntax:

PAUSE [n]

The Java syntax:

pause() or
pause(double seconds) or
pause(NumberType seconds)

The version of the implementation will depend on the time specification in the 4GL counterpart. In case of using a wait time the default message is extended by inserting “Pausing for n seconds.” in the front of the message.

The simple example in 4GL

message "Initial message".
pause 5.
message "Message after 5 sec pause".

will be implemented in Java as:

message("Initial message");
pause(5);
message("Message after 5 sec pause");

The screen after starting the application:

When 5 second interval is elapsed the message area is automatically updated to:

The same result can also be reached if the key is pressed within this time frame.

PAUSE [MESSAGE message | NO-MESSAGE]

This form of PAUSE statement can be used to redefine the default status line displaying when the statement is active. There are two options to change the behavior:

  • redefine the default status line with a new one (MESSAGE message)
  • disable any status line drawing while the message is active (NO-MESSAGE)

The 4GL syntax:

PAUSE MESSAGE message
or
PAUSE NO-MESSAGE

The Java syntax:

pause(character message), pause(java.lang.String message)
or
pause(java.lang.String null)

To disable status line activity during pause pass null as the argument to the pause() call.

In the first example we redefine the default status line for MESSAGE statement. The 4GL code

pause "Status line replacement for PAUSE. Press a key to continue".

will be implemented in Java as:

pause("Status line replacement for PAUSE. Press a key to continue");

The screen will be:

The second example demonstrates NO-MESSAGE option. 4GL statements:

pause "The next pause will not have any message. Press a key twice".
pause no-message.

will be implemented in Java as:

pause("The next pause will not have any message. Press a key twice");
pause((String) null);

After pressing a key in the first pause the screen becomes blank without any status line info. The status line changes made in pause() call will not be saved. This means after pause(null) the next pause() call without arguments will display the default status line.

PAUSE [ BEFORE-HIDE ]

This form of the PAUSE statement is used when it is required for the user to press a key or wait for some time before a frame will be automatically hidden. This just sets this behavior as the default for the runtime.

The 4GL syntax:

PAUSE [n] BEFORE-HIDE

The Java syntax:

pauseBeforeHide() or
pauseBeforeHide({character | java.lang.String} message) or
pauseBeforeHide({double | NumberType} seconds) or
pauseBeforeHide({double | NumberType} seconds, {character | java.lang.String} message)

In the sample below to demonstrate this behavior there is a loop of 100 iterations to display lines, then hide the frame and display a different frame. The hiding is done implicitly when the frame goes out of scope. Before the frame is actually hidden, there will be a 5 second pause to allow the user to see the frame before it is gone. The status message informs the user to wait for 5 seconds. This will occur after the loop completes and before the frame disappears:

pause 5 before-hide message "Pausing 5 seconds".
do i = 1 to 100:
   display "Iteration number" i with frame f1.
end.
hide all.
display "Iteration completed" i with frame f2 no-labels.

The Java implementation will be:

pauseBeforeHide(5, "Pausing 5 seconds");
loopLabel0:
for (i.assign(1); _isLessThanOrEqual(i, 100); i.increment())
{
   FrameElement[] elementList0 = new FrameElement[]
   {
      new Element("Iteration number", f1Frame.widgetExpr1()), new Element(i, f1Frame.widgeti())
   };

   f1Frame.display(elementList0);

   frame0.down();
}

hideAll(false);
...

The screen before the first frame will be automatically hidden is:

After 5 seconds of waiting the screen become:

Screen Size and Attributes

SCREEN-LINES Function

The SCREEN-LINES function returns the number of lines available to display frames. This value excludes the specially reserved message line and status line areas. This is useful if the application layout is dependent upon the working terminal size.

The 4GL syntax:

screen-lines

The Java syntax:

getScreenLines()

The function is implemented in the LogicalTerminal class. The code below will display the working size of the terminal in the message area:

4GL sample:

message "The screen lines value for the current terminal is:" screen-lines.

with Java implementation:

message(new Object[]
{
   "The screen lines value for the current terminal is:", getScreenLines()
});

The value returned from the function depends on the current terminal size and can be different from time to time if the size is changed between such calls. This example will have the following picture for the 80x24 terminal on Linux:

SESSION System Handle

This is the handle of the current Progress session object. The object allows to read and modify current Progress session context. There are a set of attributes and methods to be used for gathering session information or modify session behavior. Some of the features are supported in converted Java code but some are not.

The supported attributes of the SESSION handle:

4GL Syntax 4GL Data Type Supported Description
DISPLAY-TYPE CHARACTER Yes Display type for the session
HEIGHT-CHARS DECIMAL Limited 1 Display height in character units
HEIGHT-PIXELS INTEGER Limited 1 Display height in pixels
WIDTH-CHARS DECIMAL Limited 1 Display width in character units
WIDTH-PIXELS INTEGER Limited 1 Display width in pixels

Note 1 . limited support means here the 4GL code will be properly converted but in FWD runtime the call is not yet supported.

SESSION:DISPLAY-TYPE Attribute

This attribute contains the character interpretation of the current type of the display. The result can be either “GUI” for graphical display or “TTY” for a character-mode display. The attribute is read-only.

The 4GL syntax:

SESSION:DISPLAY-TYPE

is implemented in Java as static method of the LogicalTerminal class:

getDisplayType()

The sample to demonstrate usage of the attribute in 4GL:

message "You are currently using the display type:" session:display-type.

will be implemented in Java as:

 message(new Object[]
{
   "You are currently using the display type:", LogicalTerminal.getDisplayType()
});

The screen for Linux character based terminal is:

The current return value for FWD character based environment on Windows will also be “TTY”.

SESSION:HEIGHT-CHARS Attribute

This attribute holds the height of the display in character units. This will correspond to the value 24 for a terminal of size 80x24.

The 4GL syntax:

SESSION:HEIGHT-CHARS

is converted to Java as

LogicalTerminal.getHeightChars()

The return value is DECIMAL. However this call is not currently supported in FWD except the conversion process. It is not possible to compile the resulting Java application. The attribute is valid only for Windows graphical interface according to the 4GL documentation (the current implementation of the FWD is character based).

SESSION:HEIGHT-PIXELS Attribute

This attribute holds the height of the display in pixels. This is not the same as height in chars.

The 4GL syntax:

SESSION:HEIGHT-PIXELS

is converted into Java as

LogicalTerminal.getHeightPixels()

The return value is INTEGER. This call is only partially supported in FWD. The conversion is performed without problems and the Java application is compiled. But the current implementation of the FWD runtime just generates an exception. The attribute is valid only for a Windows graphical interface according to the 4GL documentation (the current implementation of the FWD is character based).

SESSION:WIDTH-CHARS Attribute

This attribute holds the width of the display in character units. This will correspond to the value 80 for the terminal of the size 80x24.

The 4GL syntax:

SESSION:WIDTH-CHARS

is converted into Java as

LogicalTerminal.getWidthChars()

The return value is DECIMAL. This call is not currently supported in FWD except the conversion process. It is not possible to compile Java application. The attribute is valid only for Windows graphical interface according to the 4GL documentation (the current implementation of the FWD is character based).

SESSION:WIDTH-PIXELS Attribute

This attribute holds the width of the display in pixels. This is not the same as width in characters.

The 4GL syntax:

SESSION:WIDTH-PIXELS

is converted into Java as

LogicalTerminal.getWidthPixels()

The return value is INTEGER. This call is only partially supported in FWD. The conversion is performed without problems and the Java application can be compiled. But the current implementation of the FWD runtime just generates an exception when this is called. The attribute is valid only for Windows graphical interface according to the 4GL documentation (the current implementation of the FWD is character based).


© 2004-2017 Golden Code Development Corporation. ALL RIGHTS RESERVED.