Eloquence A.05.01 Enhancements

The following enhancements have been implemented with Eloquence A.05.01:


DBMODS input redirection

The dbmods utility program does now accept input redirection. The input file syntax is according to eloq or eloqcore.

The following example will use dbmods utility program to create a schema text file db.schema from database /usr/sqlr/db/db:

   #!/bin/sh
   /usr/eloquence/dbmods <<!EOF
   /usr/sqlr/db/db
   :key#1
   :key#5
   :key#2
   db.schema
   YES
   :key#8
   !EOF


DBIMPORT, DBEXPORT field separator

New commandline options:
   -f sep  - field separator, default is ','
The -f commandline option defines a different field separator. The default field separator is a comma (',').

Dbexport/dbimport utility programs may be used to export data from a Eloquence database to an external application or to import data into a Eloquence database. The -f commandline option makes it possible to define a different field separator character.


DBIMPORT, DBEXPORT performance enhancement

The dbimport and dbexport utility programs use the regular database runtime to access the database. A remarkable amount of time is spent on synchronisation of processes for database access, while it's most often acceptable, that these programs use exclusive access.

With Eloquence A.05.01 there are special dbimport and dbexport utility programs called dbimports and dbexports, which use a optimized database runtime. Performance tests prooved a performance gain of 30% to 50%.


Maximum number of open files

The maximum number of files, that may be ASSIGNed at one time has been extended from 10 to 20.

When the limit of maximum number of open files is exceeded, a runtime error 1000 ("System files table full or maximum number of files already assigned") is returned by the ASSIGN statement.

Please note, that you still can ASSIGN only 10 files per segment.


HOP key

In addition of entering the HOP statement in order to execute a 'step over' or 'advanced step' operation during program debugging, you may now press ^G (ctrl-G).


Program file size limit

Eloquence program files are no longer limited to a file size of 64k.

Due to HP260 program format limitations, an Eloquence program file was limited to a size of 64 Kb.

An error 63 ("Number of records or bytes per record exceeds 999999 or program too big") was returned, if you tried to store a program, which exceeded the 64 Kb file limit.

If a program requires more than 64 Kb to store, a different program file format is used. Programs below 64 Kb will continue to use the former program file format to ensure compatibility with former Eloquence releases.
A program with a file size above 64 Kb will not be compatible with former Eloquence releases.


LASTLINE

The LASTLINE keyword does return the last line number used in current program. This makes it more convenient, to dynamically load subprograms or functions below the end of the program.

For example:

   LOAD SUB "SUBX",LASTLINE+1,1
will load the subprograms and functions from program file SUBX renumbering to the next available line number.


Eloquence keyboard handling

Two new statement groups allow better control of the Eloquence keyboard processing.

Typeahead

Eloquence normally rejects any key pressed while it is busy with a beep signal. The TYPEAHEAD statement enables the program to control Eloquence keyboard handling.

TYPEAHEAD n

The typeahead statement adjusts the keyboard mode. Changing the keyboard mode implies a TYPEHEAD CLEAR operation.
   n = 0 - Default behaviour. Any key pressed while Eloquence
           is not in input state will be rejected.

   n = 1 - Partial typeahead. Any key, which is not a function key
           is saved in a typehead buffer for later processing.
           Function keys are executed immediately.

   n = 2 - Full typeahead. All keys are saved in the typeahead buffer
           for later processing.
Please note:

TYPEAHEAD CLEAR

Clear the typeahead buffer. If a character is currently in typeahead buffer, a beep is output to indicate the loss of input.

N=TYPEAHEAD

The typeahead function returns the number of characters currently in typeahead buffer.

Keyboard mapping

ON KEYBD #

The ON KEYBD # statement makes it possible to use arbitrary keys like functions keys.
ON KEYBD #n[,#n...][,priority] {GOTO|GOSUB|CALL} Target

OFF KEYBD #

The OFF KEYBD # removes the interrupt handling for the specified key or all keys, if no key number has been specified.
OFF KEYBD #[n[,n...]]

LASTKEY

The LASTKEY keyword returns the key number of the last key that caused an ON KEYBD interrupt.

CURKEY

The CURKEY keyword returns 55 if the last interrupt was caused by an ON KEYBD statement.

Please note:


store utility enhancements

New commandline options:

   -t wdth = tab width (default is 8, 0 = off)

      When editing your programs in an HP-UX editor (like vi) rather
      than the integrated Eloquence editor, tab characters provide
      a convenient way to format your source code.
      Tab characters in the source code caused a syntax error.
      When specifying a tab width, all tab characters read from
      input file are replaced by the apropriate number of spaces.
      A zero tab width will disable tab expansion.
      This may also be controlled by the $TAB directive.

   -f lno  = first line number (default is 1)

      When no line numbers are included in source code, store will
      provide its own, starting with 1.
      This commandline switch makes it possible to define the first
      line number to use for automatically generated line numbers.
      This may also be controlled by the $LINE directive.

   -i inc  = line number increment (default is 1)

      This commandline switch makes it possible to define the increment,
      used for automatically generated line numbers.
      This may also be controlled by the $LINE directive.

Directives:

The following directives, if included in the source code, make it possible to control the behaviour of some store options within the code.
   $TAB wdth

      This will define a different tab character handling.
      For example:

         TAB 8

         Will define the tab expansion to 8 for subsequent
         source lines.

   $LINE fline,inc

      This will define a different automatically generated line numbers.
      For example:

         $LINE 1000,10

         Will preset the next automatically generated line number
         to 1000 and the line increment to 10.

         $LINE 1000

         Will preset the next automatically generated line number
         to 1000 and the line increment to 10.

Eloquence DLG enhancements

ListBox object

EditText object

Dialog object

The dialog object type supports the alt attribute. If it is nonzero, it is the key number of the key to be used as an ALT key in this dialog. The alt attribute must be defined in order to enable keyboard accelerators in the dialog (see below).

Keyboard accelerators

If a '&' character is contained in the label text of a object type, the following character will be displayed underlined and used as a keyboard accelerator. If the alt attribute is enabled in the dialog, pressing on the ALT key (as specified by the alt attribute) and a keyboard accelerator causes the focus to change to the first object defining the accelerator key. If the object type is StaticText, keyboard focus is changed to the next available object. If the object type is of type CheckBox, RadionButton or PushButton, the object is selected.

If pressing a key, which is not accepted by the current object (the object which got the focus), it will be used as an accelerator. For example pressing a letter, while current object is of type push putton, will cause a accelerator lookup.

For example:

      Dialog Sample {
         ...
      # Alt key is F2
         .alt = 266

         StaticText Label1 {
            ...
            .text = "Label &1"
         }

         EditText Edit {
            ...
         }
      
         PushButton OK {
            ...
            .text = "&OK"
         }
      }
Pressing the keys F2 and 1 will cause the focus changed to the EditText edit. Pressing the keys F2 and O will cause the PushButton OK to be triggered.

DLG NEW enhancements

The DLG NEW statement does dynamically creation of an dialog object. You have to specify the object path and an object type. With Eloquence A.05.01, you may specify an object path instead of the object type. The specified object and all it's children are copied to the given target path. This may also be used in a dialog description file.

For example:

      Dialog Model {

         PushButton OK {
            .text = "&OK"
            .rule = 1
         }
         PushButton HELP {
            .text = "&HELP"
            .rule = -1
         }
      }

      Dialog Sample {
         ...

         Model.OK Ok {
            .x = 10
            .y = 10
         }
         Model.HELP Help {
            .x = 20
            .y = 10
         }
      }
The pushbuttons Ok and Help will be created in the dialog Sample. All attributes are preset as specified in the dialog Model

Usage is also possible to dynamically create objects from within Eloquence:

         DLG NEW "Sample.OK","Model.OK" 
This creates the object OK in the dialog sample as specified by the object Model.OK.

DLG LOAD enhancements

In addition to dialog resource specifications, there are two additional directives supported in a dialog resource file:

The include directive

The include directive makes it possible to have common definitions among dialog files (including context specific definitions).
      include "file"
This will include the given file. If a relative path is specified, the include file is loaded relative to the path, the current dialog file is loaded from.

The file name may also contain environment variables. Environment variables are expanded in order to locate the file.

For example:

      include "$HOME/sample.inc"

      will include the file sample.inc from the home directory.

      include "sample.inc"

      will include the file sample.inc from the same directory as the
      dialog file.
If the first character, is a question mark ('?'), DLG LOAD will not fail if the include file is not present.

For example:

      include "?$HOME/sample.inc"

      will try to include the file sample.inc from the home directory.
Include file nesting is limited to two levels.

The define directive

The define directive makes it possible to use Variables in the dlg file.
      Name = value
This will associate Name with value. This name may subsequently be used to reference the associated value. If Name has already been defined, it will updated with the current value.

For example: # border types Bd_None = 0 Bd_Thin = 1 Bd_Thick = 2 Bd_shadow = 3 Bd_rshadow = 4 ALT_KEY = 266 TITLE = "Sample string" Dialog sample { ... .border = Bd_Thick .alt = ALT_KEY .title = TITLE ... }


Dialog Manager enhancements

Dialog Manager Models

The DLG NEW statement does dynamical creation of an dialog object. You have to specify the object path and an object type. With Eloquence A.05.01, you may specify a Dialog Manager Model instead of the object type.

Dialog Manager Image Button

The Dialog Manager image button object is supported with Eloquence A.05.01. It's usage is according to PushButton.

Dialog Manager Records

The DLG GET and DLG SET statement mappings have been enhanced to support Dialog Manager record objects.

DLG SET

The DLG SET statement may be used to transfer a buffer, packed by the XPACK statement, into equivalent record members of a Dialog Manager record object.
   
   DLG SET "Record.@",Buf$
Please note that the '.@' attribute must be specified.

For example:

      Windows CusWin
      {
         ...

         child record CusRec
         {
            string Cus_no shadows CusWin.Cus_number.content;
            string Cus_name shadows CusWin.Cus_name.content;
            boolean Cus_flag shadows CusWin.active;
            ...
         }
      }

      Cus_no$ = "1234"
      Cus_name$="Customer Name"
      Cus_flag=1
      XPACK Buf$ FROM Cus_no$,Cus_name$,Cus_flag
      DLG SET "CusWin.CusRec.@",Buf$

      This will transfer the variables Cus_no$, Cus_name$ and Cus_flag
      into record CusWin.CusRec.

DLG GET

The DLG GET statement may be used to transfer the contents of a Dialog Manager record object into program variables. If the '@' attribute is specified, all record members are transferred. If a member name is specified, only the given record member is transferred.
   
   DLG GET "Record.@",Buf$
   Transfer all members of Record into program variables.
   
   DLG GET "Record.Array",Buf$
   Transfer all elements of member Array.

   DLG GET "Record.Array[1]",Buf$
   Transfer the first element of record member Array.
For example:
      DLG GET "CusWin.CusRec.@",Buf$
      XUNPACK Buf$
   
      This will transfer all members of record CusWin.CusRec into
      equivalent program variables.

      DLG GET "CusWin.CusRec.Cus_flag",Buf$
      XUNPACK Buf$
   
      This will transfer the field CusWin.Cus_flag into the program
      variable Cus_flag.

Programming considerations

In order to use Dialog Manager record objects, the following considerations should be followed:

Dialog Manager functions and rules

Eloquence A.05.01 provides two new statements to make it possible to call Dialog Manager Functions and rules.

Rules are implemented using the Dialog Manager script language and are stored in the dialog resource file. This makes it possible to provide a task oriented interface to dialog without having to care about the bits and pieces.

Functions in this context are C functions linked to dialog server. The funtion must be bound to the dialog server (using DM_BindCallBacks()) and been declared in the dialog file. This makes it possible, to call your own dialog server extensions.

   DLG CALL RULE "Rule","Object" [(arg, arg ...)] [,Retvar[$]] [;Err]
Call a subprogram, implemented in Dialog Manager script language. If a return variable is present, the value returned by the rule will be assigned to it. If no return variable is specified, the return value will be ignored. If the Error return variable is present, no runtime error is returned, but Error variable is set with the error number. This is mapped to a DM_CallRule() function call.
   DLG CALL FUNCTION "FunctionName" [(arg, arg ...)] [,Retvar[$]] [;Err]
Call a C function bound to the dialog server. If a return variable is present, the value retured by the C function will be assigned to it. If the Error return variable is present, no runtime error is returned, but Error variable is set with the error number. This is mapped to a DM_CallFunction() function call.

The maximum number of arguments is 8.

If no dialog driver has been activated, an error 1004 is returned.

Accessing Dialog Manager objects

Eloquence only knows about a subset of Dialog Manager objects and attributes as necessary to translate Eloquence dialogs to Dialog Manager.
In order to enable access to Dialog Manager objects and attributes not available to Eloquence Dialog there is a 'passby option' built in Eloquence.

If you use an exclamation mark ('!') instead of a dot ('.') as a separator between object path and attribute, no mapping will be performed. This makes it possible, to access native Dialog Manager objects like menu bars and items.

Please note that only attributes, which are convertible to string or integer data type may be used.

For example:

   DLG SET "YourWindow.Edit!format","%8'3,02sf/1"
The DLG SET statement above will set the field format of the edittext object Edit.


XPACK, XUNPACK statements

The XPACK and XUNPACK statements provide a convenient way to transfer string and numeric data to and from a string variable. They are particular useful in conjunction with Dialog Manager record objects.

Unlike the PACK USING and UNPACK USING statements, the XPACK and XUNPACK statements include the variable name in the packed string and use a variable length string format.


The XPACK statement

The XPACK statement transfers data from each variable of the variable list to the destination string. A variable list may be specified in three different ways:
  1. a string expression evaluating in a variable list
  2. a variable list
  3. a reference to IN DATA SET LIST variable lists
A reference to a whole array will be resolved into a list of array elements. As the data is transferred to the destination string, it is converted into string format and stored along with the variable name and array index.
XPACK Dest$ USING <string expression>
Pack destination string variable from variable list specified by the string expression. The string expression contains a list of variable names separated by a comma.

For example:

   List$="A,A$,B,B$,A$(1),Array$(*)"
   XPACK Dest$ USING List$
XPACK Dest$ FROM Variable[,Variable ...]
Pack destination string variable from variable list.

For example:

   XPACK Dest$ FROM A,A$,B,B$,A$(*)
XPACK Dest$ USING REMOTE LISTS Line_id[,Line_id ...]
Pack destination string variable from variable list as defined by the referenced remote list(s).

For example:

   XPACK Dest$ USING REMOTE LISTS Label1,Label2
   Label1: IN DATA SET LIST A,A$
   Label2: IN DATA SET LIST ...


The XUNPACK statement

The XUNPACK statement transfers data from a string variable into the original variables. If a variable list is specified, only those variables are unpacked, that are included in the variable list.

Please note that it's not possible to unpack a buffer into a different variable than used to pack the buffer.

XUNPACK Buf$
Unpack buffer variable into variables as named in the buffer.

For example:

   A$="Test"
   B=123
   XPACK Buf$ FROM A$,B

   A$=""
   B=0
   XUNPACK Buf$
This recovers the initial values of A$ and B.
XUNPACK Buf$ USING <string expression>
Unpack buffer variable into variables as named in the buffer. The string expression contains a list of variable names separated by a comma. Only variables included in the variable list are unpacked.

For example:

   XPACK Buf$ FROM A$,B,C

   List$="A$,B"
   XUNPACK Buf$ USING List$
This unpacks the variables A$ and B only.
XUNPACK Buf$ FROM Variable[,Variable ...]
Unpack buffer variable into variables as named in the buffer. Only variables included in the variable list are unpacked.

For example:

   XPACK Buf$ FROM A$,B,C
   XUNPACK Buf$ FROM A$,B
This unpacks the variables A$ and B only.
XUNPACK Buf$ USING REMOTE LISTS Line_id[,Line_id ...]
Unpack buffer variable into variables as named in the buffer. Only variables included in the referenced REMOTE LISTS list are unpacked.

For example:

   XPACK Buf$ FROM A$,B,C
   XUNPACK Buf$ USING REMOTE LISTS Label
   Label: IN DATA SET LIST A$,B


XPACK format description

Each variable in a XPACK statement is converted into a string format containing fields describing variable type, name, index and value.

The following rules apply:

Format fields

  --------------------------------------
  |Type Name ~ Idx ~ Len ~ Value ...   |
  --------------------------------------

   ~    = Field separator. Tilde character ('~').

   Type = field type. single character.
          N = numeric
          X = string
          $ = End-of-list

   Name = field name. Up to 15 characters.
          Must be valid Variable name.
          Trailing $ of string variables is omitted.

   Idx  = Array index. 0 = simple variable.
          First array element is 1 (independent of array bounds 
          and number of dimensions).

   Len  = Size (number of bytes) of value field.

   Value= Value field. Any number of characters.

Simple variable example:

   Simple = 47
   XPACK Buf$ FROM Simple
Results in the following buffer:
   "NSimple~0~2~47$"
Equivalent Eloquence code:
   Buf$="N"&"Simple~"&"0~"&VAL$(LEN(VAL$(Simple)))&"~"&VAL$(Simple)&"$"
   Simple$ = "String"
   XPACK Buf$ FROM Simple$
Results in the following buffer:
   "XSimple~0~6~String$"
Equivalent Eloquence code:
   Buf$="X"&"Simple~"&"0~"&VAL$(LEN(Simple$))&"~"&Simple$&"$"

Array element example:

   A$(1)="TEST"
   XPACK Buf$ USING "A$(1)"
Results in the following buffer:
   "XA~1~4~TEST$"

Array example:

   DIM A$(0:3)
   A$(0)="000"
   A$(1)="111"
   A$(2)="222"
   A$(3)="333"
   XPACK Buf$ FROM A$(*)
Results in the following buffer:
   "XA~1~3~000XA~2~3~111XA~3~3~222XA~4~3~333$"

Example Eloquence XUNPACK code

The example program below shows how to unpack a buffer in XPACK format. Please note, that this example has been provided only for clarification of XPACK format.

DIM Type$[1], Var_name$[15], Value$[80], Variable$[22]
INTEGER P, Idx, Len

LOOP   
   Type$=Buf$[1,1]            ! Type
   EXIT IF Type$="$"
   Buf$=Buf$[2]
   
   P=POS(Buf$,"~")            ! locate separator
   Var_name$=Buf$[1;P-1]      ! Variable name
   Buf$=Buf$[P+1]
   
   P=POS(Buf$,"~")            ! locate separator
   Idx=VAL$(Buf$[1,P-1])      ! Array index
   Buf$=Buf$[P+1]

   P=POS(Buf$[P],"~")         ! Separator
   Len=VAL(Buf$[1,P-1])       ! Value length
   Buf$=Buf$[P+1]

   Value$=Buf$[1;Len]         ! Value
   Buf$=Buf$[Len+1]

   IF Idx THEN
      Variable$=Var_name$&"("&VAL$(Idx)&")"
   ELSE
      Variable$=Var_name$
   ENDIF

   IF Type$="X"
      COMMAND Variable$&"$=Value$"
   ELSE
      COMMAND Variable$&"="&Value$
   END IF
END LOOP

Last update: 95/08/22