FORM SET SAVE

Allows the recording of keystrokes during FORM INPUT.

Syntax

FORM SET SAVE ON|OFF

Comments

The command FORM SET SAVE ON initiates capturing the keystrokes and storing them in a script called zfmkeys in the database directory.

The command FORM SET SAVE OFF stops capturing the keystrokes.

For more information, please consult Capturing_and_Replaying_Form_Input.

FORM SET INPUT

Allows or disables the replaying of stored keystrokes during FORM INPUT.

Syntax

FORM SET INPUT ON|OFF

Comments

The command FORM SET INPUT ON initiates replaying the keystrokes stored in a script file called zfmkeys in the database directory.

The command FORM SET INPUT OFF stops replaying the keystrokes.

For more information, please consult Capturing_and_Replaying_Form_Input.

WINDOW SET MOUSEPOINTER

Display a user-defined cursor when the mouse hovers over a graphical formfield widget.

Syntax

WINDOW SET (MOUSEPOINTER ) []

Parameters

A string or an expression that evaluates to a string; the string must be a valid cursor file name.
An optional window name. The default is the current window.

Comments

Every graphical formfield widget can have a user-defined cursor displayed when the mouse is hovering over it. Unlike predefined mouse cursors, user defined mouse cursors are displayed even if the field is guarded. User-defined cursors can be assigned statically in the Screen Painter or dynamically using the MOUSEPOINTER attribute in the existing WINDOW SET command.

Working with Sets in ZIM

Understanding Result Set References in Zim

Introduction: Result set references in Zim are crucial for managing and manipulating data efficiently. This guide provides detailed examples to illustrate how result set references are compiled and highlights situations to avoid for optimal performance.


Example 1: Basic Result Set Creation

procedure test()
   find all Employees -> EmpSet
   ... other non-FIND commands ...
   find all Departments -> DeptSet
   ... other non-FIND commands ...
endprocedure
  • Explanation: This procedure creates two result sets, EmpSet and DeptSet. The compiler assumes references to the current set are to EmpSet until the second FIND command, after which references apply to DeptSet.

Technical Insight:

  • Compiler Behavior: The compiler processes commands sequentially. After the first FIND command, any reference to the current set points to EmpSet. After the second FIND, references switch to DeptSet.

Example 2: Conditional Result Set Creation

procedure GetEmps (DeptNo, NewDeptNo)
   if DeptNo = 'D01'
      find all Employees where DeptNum = DeptNo
   else
      find all Departments where DeptNum = DeptNo
   endif
   change all CurrentSet let DeptNum = NewDeptNo
endprocedure
  • Explanation: The DeptNum reference in the CHANGE command is understood by the compiler to refer to the result set created by the second FIND command, causing unexpected behavior.

Technical Insight:

  • Implicit Result Set: The CHANGE command operates on the current set, which is determined by the last FIND command executed. This can lead to ambiguity if not managed carefully.

Example 3: Using External Result Sets

procedure test2()
   form open MyForm
   change MyForm from EmpSet
   form display
endprocedure
  • Explanation: EmpSet must be a set object in the application database or created by a set-processing command before compiling test2.

Technical Insight:

  • Set Object Requirement: Ensure that EmpSet exists and has the expected structure before using it in procedures. This can be achieved by creating a “dummy” set during compilation.

Example 4: Context-Sensitive Result Sets

procedure GetSet1 (a,b)
   if a=b
      find all Employees WorkIn Departments -> set1
   else
      find all Employees -> set1
   endif
   list set1
   bottom set1
   list set1
endprocedure
  • Explanation: Using set1 with different structures causes the compiled program to not work as expected. Ensure all FIND commands producing set1 have the same structure.

Technical Insight:

  • Consistent Structure: Maintain a consistent structure for result sets to avoid compilation issues. Use SET CHECKSETS ON to enforce continuity of structure.

Example 5: Consistent Result Set Structure

procedure GetSet1 (a,b)
   if a=b
      find all Employees WorkIn Departments -> set1
   else
      find all Employees WorkIn Departments where LastName = 'Smith' -> set1
   endif
   list set1
   bottom set1
   list set1
endprocedure
  • Explanation: Ensuring set1 has the same structure in all FIND commands avoids issues.

Technical Insight:

  • Compiler Consistency: The compiler can resolve references correctly when the structure of the result set remains consistent across different FIND commands.

Example 6: Resolving Field References

procedure test3 (a,b)
   if a=b
      find Employees -> EmpSet
   else
      find Departments -> DeptSet
   endif
   if a=b
      let a = LastName
   endif
endprocedure
  • Explanation: The compiler cannot resolve LastName in the LET command because it is not a field in the current set (DeptSet). It treats LastName as a character literal.

Technical Insight:

  • Field Resolution: The LET command can only refer to fields in the current set. Ensure the correct set is active when referencing fields.

Solutions to Example 6

Example 7: Save LastName in a Variable

procedure test3 (a, b, SavedLastName)
   if a=b
      find Employees -> EmpSet
      let SavedLastName = LastName
   else
      find Departments -> DeptSet
   endif
   if a=b
      let a = SavedLastName
   endif
endprocedure
  • Explanation: Save LastName in a variable immediately after finding EmpSet.

Technical Insight:

  • Variable Storage: Storing field values in variables ensures they are accessible even if the current set changes.

Example 8: Remove FIND to Another Procedure

procedure test3 (out a, b)
   if a=b
      find Employees -> EmpSet
   else
      findDeptSet % Call a program to find DeptSet.
   endif
   if a=b
      let a = LastName
   endif
endprocedure
  • Explanation: Remove the FIND command for DeptSet to another procedure.

Technical Insight:

  • Procedure Separation: Separating FIND commands into different procedures can prevent conflicts and ensure correct field references.

Example 9: Use SET CURRENTSET

procedure test3 (a, b)
   if a=b
      find Employees -> EmpSet
   else
      find Departments -> DeptSet
   endif
   if a=b
      set currentset EmpSet
      let a = LastName
   endif
endprocedure
  • Explanation: Use SET CURRENTSET to make EmpSet the current set inside the second IF statement.

Technical Insight:

  • Current Set Management: Explicitly setting the current set ensures the correct fields are referenced, avoiding ambiguity.

Conclusion: Understanding how result set references are compiled and managed in Zim is essential for developing robust applications. By following these examples and technical insights, developers can avoid common pitfalls and ensure their programs work as expected.

Macro Substitution

A macro can appear anywhere and can be repeated any number of times in an application program.

Each time the software encounters a call to the macro, it substitutes the current character string value of the macro. Substitution takes place one command at a time, before each command is executed. To view these substitutions as they occur, issue a SET LEXTRACE ON command.

Consider a macroprogram called ShowSubstitution that contains the following line:

list #<1> Employees #<2> LastName = '#<3>' #<SortOrder>

If the commands shown below were used to execute the macroprogram ShowSubstitution

let <SortOrder> = 'Sorted by DeptNum'
ShowSubstitution "2" "where" "Smith"

then the LIST command shown above would be interpreted as

list 2 Employees where LastName = 'Smith' Sorted by DeptNum

Avoiding Macro Substitution

To use a character literal that could be mistaken for a macro – that is, the character literal contains the number sign and the macro name delimiters (#<1> or #) – you must employ the backslash (“\”, the escape character) to indicate that the number sign is to be taken literally.

For example, in the command

output 'The #<apples> in the box #<1> is:'

#<apples> and #<1> are recognized as macros. If they are not intended to be macros and therefore have not been previously defined, they are automatically replaced with the null string. Thus the command becomes

output 'The  in box  is:'

If the escape character precedes the number sign, the number sign is taken as a literal character as in:

output 'The \#<apples> in box \#<1> is:'

Nested Macros

The character string that a macro represents can contain references to other macros.

ZIM automatically performs multiple rounds of substitution when macros are nested outside quoted strings. If a nested macro appears inside a quoted string, macro substitution occurs only once.

Example

Consider two macros #<mac1> and #<mac2>. The following command could  be used to assign character strings to these macros:

let <mac1> = 'put' 
let <mac2> = 'out\#<mac1>'

Note the use of the backslash (“\”) to avoid macro substitution in the assignment to <mac2>

<mac1> put
<mac2> out\#<mac1>

With this arrangement, the command

#<mac2> 'Hello'

becomes

out#<mac1> 'Hello'

which in turn becomes

output 'Hello'

On the other hand, the command

output '#<mac2>'

is processed as

output 'out#<mac1>'

Decimals and Rounding

The result of an arithmetic expression contains as many decimal places as are found in the operands of the expression.

If the expression contains several operands with varying numbers of decimal places, the result takes on the number of decimal places found in the operand with the most decimal places.

If the result of the expression is assigned to an object with a numeric data type, the value takes on the number of decimal places defined for that object. If the object has fewer rounded decimal places than the expression’s result, the final value is rounded as shown in the following example:

5/2

Evaluates to 3

5/2.0

Evaluates to 2.5

1+1.01

Evaluates to 2.01

1.01+(5/2)

Evaluates to 3.51

Rounding occurs only after the entire expression has been evaluated. Therefore, in 1.01+(5/2), the fractional part of 5/2 is kept during the addition of 1.01. Because 1.01 has two decimal places, the result also has two decimal places.

Arithmetic with Dates

ZIM-X provides a number of built-in functions to perform date and time arithmetic.  If an arithmetic expression subtracts one date from another (i.e., both operands are of data type DATE), the result is a number representing the number of days between the two dates.

Example

Consider the Date Type values: Date1 = 19990923 (23SEP1999) and Date2 = 19980923 (23SEP1998).  We can now apply arithmetic to the dates by simply doing the following:

Date1 – Date2 evaluates to 365. Because the numbers are Date Types, ZIM equates to Date1 to 19990923 and Date2 to 19980923. If the same calculation was performed with INT Data Types the result would be 10,000.

If you add (subtract) a value that is not a date to (from) a date, the result is a date equal to the date operand plus (minus) the number of DAYS indicated by the non-date operand.

Date1 - 100 equates to 19990923 - 100, but evaluates to 19990615 (15Jun1999 - not 19990823)
Date1 + 100 equates to 19990923 + 100, but evaluates to 20000101 (1Jan2000- not 19991023)

Comments

You can covert a Number Type value to do a Date Type value by using $todate().

If you use dates in any other type of operation, the dates are treated as numbers:

Date1/100 equates to 19990923/100, and evaluates to 199909.

See Also

$addyears

$addmonths

$addminutes

$addhours

How To Construct Arithmetic Expressions

Writing Expressions

Arithmetic operators and parentheses can be combined to create long, complex expressions. Arithmetic expressions are evaluated based on the standard rules of precedence. Parentheses alter the order of evaluation.

Spaces between operands and operators can be used for clarity, but are not required.

For example, Salary * 1.1 and Salary*1.1 are equivalent.

Data Types

Arithmetic expressions yield a numeric result (if possible).

Operands should preferably be of a numeric data type, but character types are converted into an equivalent number as shown in the following example:

” ” (a space) is 0.

“-2″+5 is 3.

“2”*”-4″ is -8.

If a character value cannot be converted to a number (e.g., “abcd”), an error message is returned and the value is treated as 0.

Decimals and Rounding

The result of an arithmetic expression has as many decimal places as are found in the operand with the most decimal places in the expression. If the result is assigned to a field, variable, or form field that has fewer decimal places than the result, the result takes on the number of decimal places in the field, variable, or form field. Results are rounded as required. Rounding occurs only after the entire expression has been evaluated as shown in the following examples:

5/2 is 3

5/2.0 is 2.5

1+1.01 is 2.01

1.01+(5/2) is 3.51

How To Use Arithmetic Expressions

An arithmetic expression is a complex value expression that consists of two or more value expressions and associated arithmetic operators.

The arithmetic operators are

  • + (Add)
  • – (Subtract)
  • ^(Exponentiation)
  • * (Multiply)
  • / (Divide)

Examples of Arithmetic Expressions

For clarity, spaces can be used between operands and operators, but they are not required.

Salary * 1.1

or

Salary*1.1

Salary + (Salary * 0.1)

(1 + InterestRate)^Years

TotalPrice/Items

SellingPrice – (SellingPrice * BulkDiscount)

See Also

About Arithmetic Expressions

Arithmetic with Dates

Decimals and Rounding

Rules of Precedence for Operators

en_CAEnglish